Introduction:
An overview of the idea of functional programming: In mathematics, a function is a set of calculation schemes with input and output, that is, "do something with something". Relatively speaking, object-oriented overemphasizes "things must be done in the form of objects", while functional thinking tries to ignore the complex syntax of object-oriented—emphasizing what to do, not what form to do. What to do, not how to do it, do we really want to create an anonymous inner class object? Do not. We just have to create an object to do this.
What we really want to do is: pass the code in the run method to the Thread class to know.
Pass a piece of code-this is our real purpose. The creation of objects is just a method that has to be adopted due to the limitation of object-oriented syntax. So, is there an easier way? If we return the focus from "how to" to the essence of "what to do," we will find that as long as we can better achieve the goal, the process and the form are actually not important.
When a thread needs to be started to complete a task, the task content is usually defined through the java.lang.Runnable interface, and the java.lang.Thread class is used to start the thread.
The traditional way of writing, the code is as follows:
1/** 2 * @Author: Auser·Jie 3 * @DATE: 2019/11/4 21:46 4 */ 5public class Demo { 6 public static void main(String[] args) { 7 new Thread(new Runnable() { 8 @Override 9 public void run() { 10 System.out.println("Multi-threaded task execution!"); 11} 12 }).start(); 13} 14}
In the spirit of "everything is an object", this approach is understandable: first create an anonymous inner class object of Runnable interface to specify the task content, and then hand it over to a thread to start.
Code analysis:
code show as below:
With the new syntax of Java 8, the anonymous inner class writing of the above Runnable interface can be equivalent through simpler Lambda expressions:
1/** 2 * @Author: Auser·Jie 3 * @DATE: 2019/11/4 21:50 4 */ 5public class Demo02LambdaRunnable { 6 public static void main(String[] args) {//start thread 7 new Thread(() -> System.out.println("Multi-threaded task execution!")).start(); 8 } 9}
This code is exactly the same as the execution effect just now, and it can be passed under the 1.8 or higher compilation level. It can be seen from the semantics of the code: we start a thread, and the content of the thread task is specified in a more concise form. There is no longer the constraint of "have to create interface objects", and the burden of "abstract method overwriting and rewriting", it's that simple!
standard format:
Lambda eliminates the object-oriented rules and regulations, and the format consists of 3 parts:
The standard format of lambda expression is:
1(parameter type parameter name) -> {code statement}
Format description:
Anonymous inner class compared with lambda:
1/** 2 * @Author: Auser·Jie 3 * @DATE: 2019/11/4 21:58 4 */ 5new Thread(new Runnable() { 6@Override 7public void run() { 8 System.out.println("Multi-threaded task execution!"); 9 } 10 }).start()
Carefully analyze the code, the Runnable interface has only one definition of run method:
1() -> System.out.println("Multi-threaded task execution!")
The following example demonstrates the usage scenario code of the java.util.Comparator interface, where the abstract method is defined as:
When you need to sort an array of objects, the Arrays.sort method requires an instance of the Comparator interface to specify the sorting rules. Suppose there is a Person class with two member variables: String name and int age:
1public class Person { 2 private String name; 3 private int age; 4 5//Omit the constructor, toString method and Getter Setter 6}
Traditional way of writing If you use traditional code to sort the Person[] array, the way of writing is as follows:
1/** 2 * @Author: Auser·Jie 3 * @DATE: 2019/11/4 22:35 4 */ 5public class TestComparator { 6 public static void main(String[] args) { 7//Object array with out-of-order age 8 Person[] array = {new Person("墨白", 19), 9 new Person("Little lemon is not sour", 18), 10 new Person("大白", 20) }; 11//Anonymous inner class 12 Comparator<Person> comp = new Comparator<Person>() { 13 @Override 14 public int compare(Person o1, Person o2) { 15 return o1.getAge()-o2.getAge(); 16} 17 }; 18 Arrays.sort(array, comp); 19//The second parameter is the sorting rule, that is, the Comparator interface instance 20 for (Person person: array) { 21 System.out.println(person); 22 } 23 } 24}
This approach seems to be "taken for granted" in object-oriented thinking. Among them, the instance of the Comparator interface (using the anonymous inner class) represents the sorting rule of "from youngest to oldest".
Code analysis:
Let's figure out what the above code really does.
Lambda writing
1/** 2 * @Author: Auser·Jie 3 * @DATE: 2019/11/4 21:50 4 */ 5public class TestComparatorLambda { 6 public static void main(String[] args) { 7 Person[] array = {new Person("墨白", 19), 8 new Person("Little lemon is not sour", 18), 9 new Person("大白", 20) }; 10 Arrays.sort(array, (Person a, Person b) -> { 11 return a.getAge()-b.getAge(); 12 }); 13 for (Person person: array) { 14 System.out.println(person); 15} 16} 17}
Omission rule
Based on the Lambda standard format, the rules for using omission are:
1. The type of the parameter in the parentheses can be omitted;
2. If there is only one parameter in the parentheses, the parentheses can be omitted;
3. If there is one and only one statement in the braces, you can omit the braces, the return keyword, and the statement semicolon regardless of whether there is a return value.
Note: After mastering these omission rules, please review the multi-threaded case at the beginning of this article accordingly
Lambda emphasizes "what" rather than "how", so any information that can be derived from the context can be omitted. For example, the above example can also use the omission of Lambda:
1Runnable interface simplified: 21. () -> System.out.println("Multi-threaded task execution!") 3Comparator interface simplified: 42. Arrays.sort(array, (a, b) -> a.getAge()-b.getAge());
Lambda's syntax is very concise, without the constraints of object-oriented complexity. However, there are several problems that need special attention when using:
Note: An interface with one and only one abstract method is called a "functional interface".