Java development program - Java8
Clock in day 43 [36] - mixed in the project and network planning
Learning content: Lambda expressionNew features in Java 8
The new features of Java 8 include functional interface, Lambda expression, Stream API, interface enhancement, Optional class, new date time API, and other new features.
What is java8, that is, jdk 1.8, is a major version of the Java language. It is the most revolutionary version after java5. Although many versions have been iterated, it is still necessary to learn the features of java8, which is very valuable.
Introduction to new features of Java 8
- Faster
- Less code (new syntax added: Lambda expression)
- Powerful Stream API
- Easy to operate
- Minimize null pointer exceptions: Optional
- Nashorn engine, which allows JS applications to run on the JVM
Lambda expression
Lambda introduction
Lambda is an anonymous function, which can be understood as a piece of code that can be passed (passing the code like data). It can be used to write more concise and flexible code. As a more compact code style, the code language is more flexible.
For this concept, don't worry about the deep meaning. Let's take a look at an example first
package java8; public class JavaTest { public static void main(String[] args){ //When I explained multithreading earlier, I already said that the second way is to implement the Runnable interface. There is only one method run under the Runnable interface Runnable test1 = new Runnable() { @Override public void run() { System.out.println("java8 Easy to use"); } }; //It should be placed in the method body, not directly in the class body test1.run();//There is no call to start here. It is not multithreading, but a simple method call /** * Runnable Since there is only one method in, we don't need to write all the Runnable objects when we create them, because there are only run methods and no other methods * probably */ Runnable test2 = () ->System.out.println("java8 Okay, good"); test2.run(); } } //Both codes here can be executed normally
So my understanding is that the middle code can be omitted where there is no second possibility. Here, a bracket is left to represent an object, followed by the method body in run, and the noun is not required; If you can omit a lot, there will be a lot. As long as you leave the key, you don't have to leave anything that won't change
public static void main(String[] args){ Comparator<Integer> compareResult = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1 > o2?1000:-1; } }; int result = compareResult.compare(13, 53); System.out.println(result); /** * The Comparator interface here also has only one method, and many of the above bytes are unnecessary, because there will be no other expression except this expression, so * Here we continue to use Lambda to simplify the code * The Integer here is variable, so take it with you * It's indicated in the front, but it's not needed in the back */ Comparator<Integer> compareResult1 = (o1, o2) -> o1 > o2?1000:-1; int result1 = compareResult1.compare(63, 53); System.out.println(result1); }
This code also directly omits many of the same parts. If you give it in front of the method name, curly braces and class name, you don't need it
Lambda is realized through the - > symbol. There can't be nothing in front of the symbol, and the expression here should be noted that the omission in the back should be concise enough
Lambda specific analysis
1. Example: () - > system. Out. Println ("java8 is very good");
2. Format: the operator of Lambda is - >, and the name is Lambda operator
3. Explanation: the left side of the operator is the lambda formal parameter list, which is actually the formal parameter list of the abstract method in the interface, and the right side is the lambda body, which is actually the method body of the rewritten abstract method
4. Type [use]
There is only one execution statement. If there is a return value, return and braces can be omitted
-
[method in interface] no parameter, no return value
Runnable runable = () -> System.out.println("java8 Okay, good"); runnable.run();
-
There is no return value, but a parameter is required [parameter list does not need data type, but can be inferred]
The type inference is repeated here, that is, the compiler can infer the data type according to the previous code, such as the previous generic example and array creation
ArraryList<String> list = new ArrayList<>(); //You don't need to write String later here int[] arr = {1,2,3}; //The compiler infers that the object is created and is an integer, so it can be given directly
Let's take a look at the representation method after using type inference. It's really concise
Comparable<Integer> comparable = (o) -> o > 1?1000:-1; System.out.println(comparable.compareTo(34));
There is only one parameter. Removing parentheses will not cause ambiguity. Parentheses can be removed
Comparable<Integer> comparable = o -> o > 1?1000:-1; System.out.println(comparable.compareTo(34));
-
There are two or more parameters and multiple execution statements. You can write braces with the return value [the most common case]
Comparator<Integer> compareResult1 = (o1, o2) -> { System.out.println(o1); System.out.println(o2); return o1 > o2?1000:-1; }; System.out.println(compareResult1.compare(63, 53));
Here, there is more than one method body sentence, so multiple lines should be written. When executing, it should be executed in the order of execution
Therefore, the data type of the formal parameter list on the left of the operator can be omitted, and only one parameter can omit parentheses; For the right lambda body, if there is only one line of statement, return and braces can be omitted
5. Essence: the essence of a lambda expression is an instance of an interface, which means that the expression is an object, so it is used only when creating an object, which represents an instance; You can see that the interfaces here have only one method. This interface has a specific name called functional interface
In fact, after simplification, use the methods in the interface to realize various operations. Using Lambda expression can make calling single method interface very concise
Lambda can only be used for functional interfaces
Lambda can only be used for functional interfaces, not for abstract classes with multiple methods but only one abstract method. For example, the following WindowAdapter cannot be simplified with lambda
this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { if(type == 1) { DisConnect(); } System.exit(0); } } );
You can take a look at the program error after use
Multiple markers at this line
- The target type of this expression must be a functional interface
- The method addWindowListener(WindowListener) in the type Window is not applicable for the arguments ((WindowEvent
e) -> {})
- The method addWindowListener(WindowListener) in the type Window is not applicable for the arguments ((WindowEvent
Therefore, Lambda's function is to simply create instances of functional interfaces
Functional interface
If only one abstract method is declared in an interface, the interface is a functional interface
By reading the source code, you can find the annotation [to enter the source code, directly Ctrl + Shift +T], you can enter the corresponding class to view the source code
@FunctionalInterface public interface Runnable { //This is the annotation on the source code
This annotation can be added when customizing a functional interface, and the system can check whether the interface is a functional interface.
In addition, the javadoc will also contain a declaration that the interface is a functional interface
Understanding of functional interfaces
Java has always been an object-oriented programming language, and everything is an object. For example, Lambda expression here is an object. In other functional programming languages, function attaches great importance to it, and Lambda expression is also a function. However, in java8, Lambda expression is an object, not a function, but they must depend on functional interfaces to realize it [the function in C has only one method, and the function is not defined again in the function body]
As long as an expression is an instance of a functional interface, Lambda expressions can be used for simplification. Previously used anonymous implementation classes can now be written using Lambda expressions
Four core functional interfaces built in java
- Consumer < T > consumer interface. The parameter type is t and the return value type is void. It operates on objects of type T, including void accept (T)
- Supplier < T > the parameter free return value type of the supply interface is t. The methods included are: T get();
- Function < T, R > the parameter type of the functional interface is t and the return value type is R. operate the object of type T and return the result r apply (T);
- Predict < T > determine whether the interface parameter type is t and the return type is boolean. Determine whether the object of type T satisfies a constraint and return a boolean value, including boolean test (T);
Therefore, if we find that relevant operations need to be carried out when using, we can use these methods
For example, consumer interface
package java8; import java.util.function.Consumer; public class JavaTest { //Use of java built-in functional interface //Consumer interface: pass in an object of type and manipulate the object public static void consumer(int value, Consumer<Integer> con) { con.accept(value);//Operate the object [consumption] } public static void main(String[] args) { consumer(20, t -> System.out.println(t + 1));//It's already known that it's an integer here. You don't need a type } }
Here, when we create a method, we give an object and a consumer interface. We can directly call the method of the interface to realize the operation of the interface
Another example
This is the use of assertive interfaces. In this way, when we create methods, we don't need to explicitly judge methods at the beginning, and we don't need to create another method. When calling methods, we can easily add operation methods
public static List<String> fitterList(List<String> list, Predicate<String> con) { ArrayList<String> newList = new ArrayList<>(); for(String s : list) { if(con.test(s)) { newList.add(s); } } return newList; } public static void main(String[] args) { List<String> list = Arrays.asList("Cfeng","java","study","every","day"); List<String> newList = fitterList(list, s -> s.contains("a"));//Include ava for(String s : newList) { System.out.println(s); } }
Here, the judgment method is created when filtering is needed, and because there is only one line, it can be omitted to the simplest form
There are other types in java that can be used. You can read the API documents of java and find the use of various functional interfaces
Method reference
1: Usage scenario: when the operation passed to the Lambda body already has an implemented method, you can use the method reference
2: Essence: it is a Lambda expression and an example of a functional interface
3: Understanding: self understanding is to replace the original Lambda body with another existing method
4: Classification: there are three main situations
-
Object:: non static method
-
Class:: static method
-
Class:: non static method
There is also a more concise method of use, which is method reference. Let's see the effect first
Comparator<Integer> compare2 = Integer :: compare; System.out.println(compare2.compare(10, 20));
That is, the long code above can be concise to a certain extent in this way. The omission in this way is called method reference
- If the operation to be passed to the Lambda body already has an implemented method, you can use the method reference
- A method reference is actually a lambda expression, that is, an instance of a functional interface. It is a special case of a lambda expression: a method that has been implemented by a functional interface
Method references are implemented through the:: symbol
Here are a few examples
public static void main(String[] args) { Comparator<Integer> com = Integer :: compare; //Replace the original compare method with the compare method in the Integer class System.out.println(com.compare(21, 22));//The static method referenced by the class name used PrintStream ps = System.out; Consumer<String> consume = ps :: println;// Use the instance method println instead of the original method accept consume.accept("I'm Cfeng"); }
Here are two examples, in fact, you can see the key to use; First of all, we should understand that the purpose of using functional interfaces is to call the only method in the interface for related manipulation, and the interface must implement abstract methods to create instances. Therefore, there is a Lambda expression. You can refer to an interface instance only by writing the parameter list and method body of the method in the interface; The method reference is to replace this method body with other existing methods. You can call relevant methods to replace the writing of this abstract method only by using the name:: method. Just note that the parameter list should be the same, otherwise it cannot be used normally.
Next, there are construction method references and other knowledge, which will be shared tomorrow 🌳