Write interfaces are not just CURD, but they can be more advanced, and we need to look at functional programming before we talk about reactive programming
The concept of functional programming
Use the system’s own functions and Lambda expressions for programming
To take a simple example, find the minimum of an int array
// Define an int array
int[] nums = {1.2.3.4.5};
int min = Integer.MAX_VALUE;
for (int i : nums) {
if (min > i) {
min = i;
}
}
System.out.println(min);
Copy the code
This is the traditional way, the code is very simple, and let’s look at the code for functional programming
System.out.println(IntStream.of(nums).min().getAsInt());
Copy the code
Just a line
First of all, the advantages of functional programming can be reflected from the code, the code is easy to read (first into the flow, and then find the minimum value, and then take out the minimum value)
If the numS array is too large, the efficiency of the single-thread for loop cannot meet the requirements in the traditional way. The first thought is to group the NUMS array and put it into the thread pool for processing. Finally, take out the minimum value of each group and calculate the minimum value again to get the result
Using flow and functional programming, you can change the code to the following:
System.out.println(IntStream.of(nums).parallel().min().getAsInt());
Copy the code
Simply by adding.parallel(), the flow becomes a parallel stream, automatically grouped and multithreaded, and the advantages are obvious
The function interface
Function
= Function
The @functionalInterface annotation is added to the Function
interface. This annotation defines only one method to be implemented in the interface. The default method is not included. It is natural to think that the interface implementation of a method in Lambda expressions would be more concise and consistent with the single responsibility pattern in the design pattern
Function
defines R apply(T T); T represents the input parameter type, R represents the parameter type. This method is what we will use. A simple example is used to demonstrate this
public static void main(String[] args) {
int num = 123;
// Call the test method defined below, passing in a function and data to process
String b = test(a -> String.valueOf(a), num);
System.out.println(b);
}
// Define a method whose first argument is a function and whose second argument is the data to process
public static String test(Function<Integer, String> func, int a) {
// Call the apply method of the function, passing in the argument a
return func.apply(a);
}
Copy the code
String b = test(a -> string.valueof (a), num); String b = test(a -> string.valueof (a)); Such calls are essentially anonymous implementations of the Function interface
Built-in function interface
The JDK includes several other commonly used Function interfaces
interface
|
The ginseng | return |
instructions
|
---|---|---|---|
Predicate<T> |
T | boolean | Assertion, often used for filter filtering |
Consumer<T> |
T | There is no | Only consumption data, no output, is the consumer |
Function<T, R> |
T | R | Input T, output R |
Supplier<T> |
There is no | T | No input, output T is the producer |
UnaryOperator<T> |
T | T | The input and output types are the same |
BiFunction<T, U, R> |
T, U | R | Input two parameters, output R |
BinaryOperator<T> |
T, T | T | Input two parameters T, output T, the three data type is the same |
These are just interfaces, so you can look at the source code and find the interface definition
A simple example:
// Define an assertion that the input parameter is Integer, the body of the function is less than 0, and returns a Boolean value
Predicate<Integer> a = i -> i < 0;
System.out.println(a.test(123));
Copy the code
Method references
Also to simplify the code, there are the following reference methods
Static method reference
Function<Integer, String> func = a -> String.valueOf(a);
System.out.println(func.apply(123));
Copy the code
In a -> string.valueof (a) above, valueOf is a static method, which can be abbreviated as
Function<Integer, String> func = String::valueOf;
System.out.println(func.apply(123));
Copy the code
A non-static reference
public static void main(String[] args) {
Test02 test02 = new Test02();
Function<Integer, String> func = test02::b;
System.out.println(func.apply(123));
}
public static class Test02 {
public String b(Integer a) {
returnString.valueOf(a); }}Copy the code
Constructor reference
public static void main(String[] args) {
// No arguments
Supplier<Test02> s1 = Test02::new;
System.out.println(s1.get());
// There are parameters
Function<Long, Test02> s2 = Test02::new;
// The apply method passes in arguments constructed with arguments
System.out.println(s2.apply(1L));
}
@Data
public static class Test02 {
private Long id;
public Test02(a) {}public Test02(Long id) {
this.id = id; }}Copy the code
Cascade expressions/higher-order functions
The following functions are called higher-order functions
Function<Integer, Function<Integer, Integer>> func = a -> b -> a + b;
// Call higher-order functions
System.out.println(func.apply(1).apply(2));
Copy the code
A -> b -> a + b
Func.apply (1) returns b -> a + b. Func.apply (1) returns b -> a + b.
When I call.apply(2), B is the input parameter, and the output parameter is a + b, so it actually ends up being 1+2
Why bother writing it?
The goal is to convert a function of multiple arguments into a function of one argument
Code like this:
x -> y -> z = x + y + z;
Copy the code