從匿名內部類引入Lambda表達式
在線程池那篇博客中,我們通過使用匿名內部類來作爲參數傳入submit方法中。
但是我們發現,這樣雖然在步驟上簡單了許多,但是在空間上看着並不簡單,甚至顯得比較複雜。
那我們就用更簡單的lambda表達式來代替匿名內部類。
package executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo2 {
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(5);
newFixedThreadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("未自定義runnable接口實現類"+Thread.currentThread().getName());
}
});
newFixedThreadPool.submit(() ->
{
System.out.println("未自定義runnable接口實現類"+Thread.currentThread().getName());
});
newFixedThreadPool.submit(()->System.out.println("未自定義runnable接口實現類"+Thread.currentThread().getName()));
newFixedThreadPool.submit(()->System.out.println("未自定義runnable接口實現類"+Thread.currentThread().getName()));
newFixedThreadPool.submit(()->System.out.println("未自定義runnable接口實現類"+Thread.currentThread().getName()));
}
}
Lambda表達式
思想 "說重點"
lambda表達式的核心即在於說重點
以線程代碼爲例,他需要的是什麼?最核心的東西是什麼?
就是run方法!!!
runnable接口中重寫實現的就一個run方法!!!接口只是run方法的載體,裝黃桃的罐頭盒子!!!核心只要run方法。
我們爲什麼要寫runnable接口的實現類?就是爲了重寫run方法,並且讓線程去執行run方法。
所以,現在我們不要盒子了,直接用手抓着吃!!!
service.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
/*
匿名內部類方式來作爲線程池執行目標代碼
1. 這個方法需要的參數是Runnable接口的實現類對象
2. Runnable接口目標是爲了提供一個run 方法, What will be run
3. What will be run??? where??? run方法內容
這裏需要Runnable提供Run方法,提供Run方法方法體
"說重點"
需要Run方法方法體
*/
Lambda表達式格式
service.submit(() -> System.out.println(Thread.currentThread().getName()));
() -> System.out.println(Thread.currentThread().getName())
Lambda表達式
() 參數列表
-> 做什麼事情,就是對應方法體
箭頭之後的代碼就是正常語句
(參數列表) -> {代碼語句}
Lambda表達式使用,無參數無返回值
package com.qfedu.c_lambda;
/*
* 無參數無返回值
*/
interface Cook {
void cooking();
}
public class Demo1 {
public static void main(String[] args) {
invokeCook(new Cook() {
@Override
public void cooking() {
System.out.println("麻辣香鍋,孜然肉片,土豆牛肉,蒜薹肉絲");
}
});
invokeCook(() -> {
System.out.println("蒜蓉油麥菜,番茄雞蛋");
});
invokeCook(() -> System.out.println("明天早上自己炸油條"));
}
/**
* 執行Cook實現類對象方法
*
* @param cook Cook接口的實現類對象
*/
public static void invokeCook(Cook cook) {
cook.cooking();
}
}
Lambda表達式使用,有參數有返回值
這裏面用到了Arrays.sort方法
後邊是comparator接口 比較器實現
package com.qfedu.c_lambda;
import java.util.Arrays;
import java.util.Comparator;
public class Demo2 {
public static void main(String[] args) {
Person[] persons = {
new Person("騷磊", 16),
new Person("老黑", 50),
new Person("老付", 40),
new Person("污雲", 35),
new Person("朋朋", 14),
new Person("大哥", 18),
};
// public static <T> void sort(T[] a, Comparator<? super T> c)
Arrays.sort(persons, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
});
/*
* 1. 有參數
* 2. 有返回值
*
* (Person o1, Person o2) -> {
* return o1.getAge() - o2.getAge();
* }
* 標準Lambda
*/
Arrays.sort(persons, (Person o1, Person o2) -> {
return o2.getAge() - o1.getAge();
});
/*
* 1. 這裏可以省略數據類型
* 2. 可以直接利用返回值,{}和return都省了掉
*/
Arrays.sort(persons, (o1, o2) -> o2.getAge() - o1.getAge());
for (Person person : persons) {
System.out.println(person);
}
}
}
甚至還可以更加簡化,省略數據類型,但最好不要
package com.qfedu.c_lambda;
interface A {
float add(int num1, float num2);
}
public class Demo3 {
public static void main(String[] args) {
System.out.println(new A() {
@Override
public float add(int num1, float num2) {
return num1 + num2;
}
}.add(5, 13.5F));
/*
* 1. 數據類型真的可以省略,雖然是不同數據類型,Java語言真香
* 2. 實現的代碼非一行,可以在大括號內完成你的目標
*/
test(5, 13.5F, (num1, num2) -> {
float sum = num1 + num2;
return sum;
});
}
public static void test(int num1, float num2, A a) {
System.out.println(a.add(num1, num2));
}
}
Lambda表達式使用前提
-
有且只有一個缺省屬性爲public abstract方法的接口,例如 Comparator接口,Runnable接口
-
使用lambda表達式是有一個前後要求約束的方法的參數爲接口類型,或者說局部變量使用調用方法,可以使用lambda也OK
-
有且只有一個抽象方法的接口,稱之爲【函數式接口】Comparator接口,Runnable接口