Lambda expression
primary coverage
Teaching objectives
-[] be able to understand the advantages of functional programming over object-oriented - [] be able to master the standard format of lambda expression - [] be able to use lambda standard format and use runnable and comparator interface - [] be able to master the omitted format and rules of lambda expression - [] be able to use lambda omitted format and use runnable and comparator interface - [] The user-defined interface (with and only one abstract method) can be used through lambda's standard format - [] the user-defined interface (with and only one abstract method) can be used through lambda's ellipsis format - [] the two prerequisites of lambda can be clarified
Chapter 1 lambda expression
1.1 overview of functional programming ideas
In mathematics, a function is a set of calculation schemes with input and output, that is, "what to do with". Relatively speaking, object-oriented overemphasizes that "things must be done in the form of objects", while functional thinking tries to ignore the complex object-oriented syntax - emphasizing what to do rather than what form to do.
Object oriented thinking:
Do a thing, find an object that can solve it, call the method of the object, and complete the thing
Functional programming idea:
As long as the results can be obtained, it doesn't matter who does it or how to do it. It pays attention to the results rather than the process
1.2 redundant runnable code
Traditional writing
When a thread needs to be started to complete a task, it is usually through Java Lang. runnable interface to define the task content, and use Java Lang. thread class to start the thread. The code is as follows:
public class Demo01Runnable {
public static void main(String[] args) {
// 匿名内部类
Runnable task = new Runnable() {
@Override
public void run() { // 覆盖重写抽象方法
System.out.println("多线程任务执行!");
}
};
new Thread(task).start(); // 启动线程
}
}
Based on the idea of "everything is an object", this approach is understandable: first, create an anonymous internal class object of runnable interface to specify the task content, and then hand it over to a thread to start.
code analysis
For the anonymous inner class usage of runnable, several points can be analyzed:
1.3 conversion of programming ideas
What to do, not how to do it
Do we really want to create an anonymous inner class object? no We just have to create an object to do this. What we really want to do is pass the code in the run method body to the thread class.
Pass a piece of code -- that's our real purpose. Creating objects is only a means that has to be taken due to the limitation of object-oriented syntax. So, is there a simpler way? If we return our focus from "how to do" to "what to do", we will find that as long as we can better achieve the goal, the process and form are not important.
Life examples
When we need to travel from Beijing to Shanghai, we can choose high-speed rail, car, cycling or hiking. Our real goal is to get to Shanghai, and the form of how to get to Shanghai is not important, so we have been exploring whether there is a better way than high-speed rail - by plane.
Now this kind of aircraft (or even spacecraft) has been born: Java 8 (JDK 1.8) released by Oracle in March 2014 added the heavyweight new feature of lambda expression, opening the door to a new world for us.
1.4 experience lambda's better writing method
With the new syntax of Java 8, the anonymous internal class writing method of the above runnable interface can be equivalent through a simpler lambda expression:
public class Demo02LambdaRunnable {
public static void main(String[] args) {
new Thread(() -> System.out.println("多线程任务执行!")).start(); // 启动线程
}
}
The execution effect of this code is exactly the same as that just now. It can be passed at the compilation level of 1.8 or higher. From the semantics of the code, we can see that 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 "having to create interface objects", and there is no longer the burden of "abstract method override", which is so simple!
1.5 review anonymous inner classes
How does lambda beat object orientation? In the above example, the core code is just as follows:
() -> System.out.println("多线程任务执行!")
In order to understand the semantics of lambda, we need to start with traditional code.
Using implementation classes
To start a thread, you need to create an object of the thread class and call the start method. In order to specify the content executed by the thread, you need to call the construction method of thread class:
In order to obtain the implementation object of the runnable interface, you can define an implementation class runnableimpl for the interface:
public class RunnableImpl implements Runnable {
@Override
public void run() {
System.out.println("多线程任务执行!");
}
}
Then create the object of this implementation class as the construction parameter of thread class:
public class Demo03ThreadInitParam {
public static void main(String[] args) {
Runnable task = new RunnableImpl();
new Thread(task).start();
}
}
Use anonymous inner classes
This runnableimpl class exists only to implement the runnable interface and has only been used once. Therefore, using the syntax of anonymous inner class can omit the separate definition of this class, that is, anonymous inner class:
public class Demo04ThreadNameless {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("多线程任务执行!");
}
}).start();
}
}
Advantages and disadvantages of anonymous inner classes
On the one hand, anonymous inner classes can help us save the definition of implementation classes; On the other hand, the syntax of anonymous inner classes -- it's really too complicated!
semantic analysis
After careful analysis of the semantics in the code, the runnable interface has only one definition of run method:
That is, a scheme for doing things is formulated (actually a function):
The same semantics is embodied in lambda grammar, which should be simpler:
() -> System.out.println("多线程任务执行!")
1.6 lambda standard format
Lambda omits the object-oriented rules and regulations, and the format consists of three parts:
The standard format for lambda expressions is:
(参数类型 参数名称) -> { 代码语句 }
Format Description:
1.7 exercise: use lambda standard format (no parameter, no return)
subject
Given a cook interface, it contains the only abstract method makefood, with no parameters and no return value. As follows:
public interface Cook {
void makeFood();
}
In the following code, please use lambda's standard format to call the invokecook method and print out "eat!" word:
public class Demo05InvokeCook {
public static void main(String[] args) {
// TODO 请在此使用Lambda【标准格式】调用invokeCook方法
}
private static void invokeCook(Cook cook) {
cook.makeFood();
}
}
answer
public static void main(String[] args) {
invokeCook(() -> {
System.out.println("吃饭啦!");
});
}
1.8 lambda parameters and return values
需求:
使用数组存储多个Person对象
对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序
The following example demonstrates Java util. Usage scenario code of comparator < T > interface, in which the abstract method is defined as:
When you need to sort an array of objects, arrays The sort method requires a comparator interface instance to specify the sorting rules. Suppose there is a person class with two member variables: String name and int age:
public class Person {
private String name;
private int age;
// 省略构造器、toString方法与Getter Setter
}
Traditional writing
If the traditional code is used to sort the person [] array, it is written as follows:
import java.util.Arrays;
import java.util.Comparator;
public class Demo06Comparator {
public static void main(String[] args) {
// 本来年龄乱序的对象数组
Person[] array = {
new Person("古力娜扎",19),new Person("迪丽热巴",18),new Person("马尔扎哈",20) };
// 匿名内部类
Comparator<Person> comp = new Comparator<Person>() {
@Override
public int compare(Person o1,Person o2) {
return o1.getAge() - o2.getAge();
}
};
Arrays.sort(array,comp); // 第二个参数为排序规则,即Comparator接口实例
for (Person person : array) {
System.out.println(person);
}
}
}
This approach seems to be "taken for granted" in the idea of object-oriented. The instance of comparator interface (using anonymous inner class) represents the sorting rule of "from small to large by age".
code analysis
Let's find out what the above code really does.
Lambda writing
import java.util.Arrays;
public class Demo07ComparatorLambda {
public static void main(String[] args) {
Person[] array = {
new Person("古力娜扎",20) };
Arrays.sort(array,(Person a,Person b) -> {
return a.getAge() - b.getAge();
});
for (Person person : array) {
System.out.println(person);
}
}
}
1.9 exercise: use lambda standard format (return with reference)
subject
Given a calculator calculator interface with an abstract method Calc, you can add two int numbers to get the sum value:
public interface Calculator {
int calc(int a,int b);
}
In the following code, please call the invokecalc method in lambda's standard format to complete the addition calculation of 120 and 130:
public class Demo08InvokeCalc {
public static void main(String[] args) {
// TODO 请在此使用Lambda【标准格式】调用invokeCalc方法来计算120+130的结果ß
}
private static void invokeCalc(int a,int b,Calculator calculator) {
int result = calculator.calc(a,b);
System.out.println("结果是:" + result);
}
}
answer
public static void main(String[] args) {
invokeCalc(120,130,(int a,int b) -> {
return a + b;
});
}
1.10 lambda omitted format
It can be deduced and omitted
Lambda emphasizes "what to do" rather than "how to do", so any information that can be deduced from the context can be omitted. For example, the above example can also use lambda's ellipsis:
public static void main(String[] args) {
invokeCalc(120,(a,b) -> a + b);
}
Omission rule
On the basis of lambda standard format, the rules for using ellipsis are as follows:
1.11 exercise: use lambda to omit the format
subject
Still use the cook interface with the only makefood abstract method mentioned above. In the following code, please use lambda's ellipsis format to call the invokecook method and print out "eat!" word:
public class Demo09InvokeCook {
public static void main(String[] args) {
// TODO 请在此使用Lambda【省略格式】调用invokeCook方法
}
private static void invokeCook(Cook cook) {
cook.makeFood();
}
}
answer
public static void main(String[] args) {
invokeCook(() -> System.out.println("吃饭啦!"));
}
1.12 premise of lambda
Lambda's syntax is very concise and completely free from the constraints of object-oriented complexity. However, there are several problems that need special attention when using: