1, an overview of

The improvements to Java8 are more profound than any change in history. Java continues to evolve as a result of changes in the programming language’s ecology — big data, for example, needs to run on multiple cores, which Java didn’t previously support.

Prior to Java8, if you wanted to leverage multiple computer kernels, you used threads and had to deal with complex synchronization logic. But in Java8, you can easily use streams to make your code run across multiple kernels.

It also borrows from other languages and open source libraries, such as Scala, Guava, etc. Let’s summarize the main features or improvements of Java8:

  1. Functional programming and Lambda expressions;
  2. Stream programming;
  3. Time API improvements;
  4. The default method

2. Parameterize behavior

“Behavior” refers to methods, and “behavior parameterization” refers to passing in methods as parameters, which in plain English refers to policy patterns. Java8 simply uses Lambda expressions to simplify anonymous class code and make it look more concise. There’s not a lot you need to know in this area.

2.1 Basic syntax of Lambda expressions

(parameters) -> expression // expression -> {statements; } // statements are followed by semicolons and enclosed in curly bracesCopy the code

The basic syntax for Lambda is shown above. In the first line, expressions are used in Lambda. In the second line, statements are used in Chinese Lambda.

Here are some examples of using Lambda expressions:

public static void main(String... Args) {ICreateObject createObject = Employee::new; IExpression expression = employees -> employees.get(0); // IExpression expression2 = List::isEmpty; IExpression expression2 = employees -> employees.isEmpty(); IConsumeObject consumeObject = employee -> System.out.println(employee.name); IAdd add = (a, b) -> a + b; IAdd add1 = Java8LambdaExample::cal; // Object Object = Employee::new; }Copy the code

From the example code above, we can draw some conclusions:

  1. A function interface is an interface that contains only one non-default method and can be used@FunctionalInterfaceAnnotations indicate that the specified interface is a function interface;
  2. If the Lambda->The following is the statement, and when the statement is only one line, we can remove the curly braces;
  3. When you want to assign a Lambda expression to an object, if the object is notThe function interface, then IDEA will give a hint;
  4. Also note that functional interfaces are not allowed to throw checked exceptions.

Here are some examples of common method references:

The Employee::new in the code above is what is called a method reference. Here are examples of common method references:

Serial number Lambda Equivalent method references
1 (Employee e)->e.getName() Employee::getName
2 (String s) -> System.out.println(s) System.out::println
3 (str, i) -> str.substring(i) String::substring

So, we summarize the three cases cited by the methods:

Serial number Lambda Equivalent method references
1 (Parameter) -> Class name. Static method (parameter) Class name :: static method
2 (Parameter 1, other parameters) -> Parameter 1. Instance method (Other parameters) Class name :: instance method
3 (Parameter) -> expression. Instance method (parameter) Expression :: instance method

2.2 Functional interfaces in Java APIS

The Java8 API provides several functional interfaces that are worth learning about. Since Java8 has allowed interfaces to define default methods, these interfaces provide some interesting default methods. This might be useful for our programming.

public interface Predicate<T> {
    boolean test(T t);
}

public interface Consumer<T> {
    void accept(T t);
}

public interface Function<T, R> {
    R apply(T t);
}
Copy the code

These are the definitions of the three interfaces. The difference in their application scenarios is reflected in the parameter returned:

  1. The first one is used to judge, and is roughly used to achieve the effect of filtering;
  2. The second is that there is no return type, which can only be used to process the parameters passed in.
  3. The third one is for mapping, that is, when the parameters and returns of the behavior you want to implement are of different types (of course, if they are of the same type).

Because Java does extra boxing and unboxing for numeric types, there is a cost. So, for the three interfaces above (as for the others), Java8 provides a boxed free version that goes from generics to numeric types. Take IntPredicate for example:

public interface IntPredicate {
    boolean test(int value);
}
Copy the code

2.3 Compound Lambda expressions

Some of the interfaces provided in Java8 can still be composed. More complex logic can be implemented using compound operations. These composite operations are defined in the form of default methods, with each functional interface slightly different. So, here we list only some of the methods used for composition. During actual development, you can go directly to the specified functional interface to see the definition of these methods.

2.3.1 Comparator

Suppose you have a data list employees, whose object is Employee, with methods getName() and getAge().

employees.sort(Comparator.comparing(Employee::getName));
employees.sort(Comparator.comparing(Employee::getName).reversed().thenComparing(Employee::getAge));
Copy the code

The first of the two lines of code implements sorting employees by the result of getName(). The second line of code, on employees, sorts the result of getName(), then reverses the return, and then sorts it by the result of getAge().

2.3.2 Predicates compound negate(), or(), and()

Predicate<Employee> employeePredicate = (employee -> employee.getAge() > 13)
employeePredicate.negate()
employeePredicate.and(employee -> employee.getAge() <= 15).or(employee -> "LiHua".equals(employee.getName()))
Copy the code

EmployeePredicate is defined first, which can be used to filter “employees older than 13.” Calling the negate() method returns a Predicate that can be used to filter “employees aged 13 or younger.” The final compound operation represents “an employee older than 13 and younger than 15 or an employee with the name LiHua.”

Notice that the and and or operation order is from left to right, namely a.o r (b). And (c) will be regarded as (a | | b) and c.

2.3.3 Function composition

Function has the andThen and compose default methods, both of which return a Function instance.

Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h1 = f.andThen(g); // h1(x) = g(f(x)) = (x + 1) * 2
Function<Integer, Integer> h2 = f.compose(g); // h2(x) = f(g(x)) = (x * 2) + 1
System.out.println(h1.apply(1));
System.out.println(h2.apply(1));
Copy the code

The above is an example of a compound operation for Function, which is the mathematical equivalent of a compound Function. However, it should be noted that the actual composite effect of the two methods is different.

conclusion

That’s the first part of the Java8 improvement. To summarize, behavior parameterization is really a policy pattern, and Lambda can simplify the form of function interfaces. Some useful functional interfaces are provided in the Java API, which in turn can be made more powerful by using composite methods.