非原創(chuàng),知識總結(jié)性文章
1、Lambda表達式的介紹
函數(shù)式編程思想概述
在數(shù)學中,函數(shù)就是有輸入量、輸出量的一套計算方案,也就是“拿什么東西做什么事情”。相對而言,面向?qū)ο筮^分強調(diào)“必須通過對象的形式來做事情”,而函數(shù)式思想則盡量忽略面向?qū)ο蟮膹碗s語法——強調(diào)做什么,而不是以什么形式做。
傳統(tǒng)寫法代碼示例
public class demo01 {
public static void main(String[] args) {
Runnable runnable = new Runnable(){
public void run(){
System.out.println("多線程任務(wù)執(zhí)行");
}
};
new Thread(runnable).start();
}
}
說明:
- Thread類需要Runnable接口作為參數(shù),其中的抽象run方法是用來指定線程任務(wù)內(nèi)容的核心;
- 為了指定run的方法體,不得不需要Runnable接口的實現(xiàn)類;
- 為了省去定義一個RunnableImpl實現(xiàn)類的麻煩,不得不使用匿名內(nèi)部類;
- 必須覆蓋重寫抽象run方法,所以方法名稱、方法參數(shù)、方法返回值不得不再寫一遍,且不能寫錯;
- 而實際上,似乎只有方法體才是關(guān)鍵所在
上述示例使用Lambda的寫法
public class demo01 {
public static void main(String[] args) {
new Thread(()->{
System.out.println("多線程啟動");
}).start();
}
}
上例中,核心代碼其實只是如下所示的內(nèi)容:() -> System.out.println("多線程任務(wù)執(zhí)行!")
Lambda標準格式
Lambda省去面向?qū)ο蟮臈l條框框,格式由3個部分組成:
- 一些參數(shù);
- 一個箭頭;
- 一段代碼。
Lambda表達式的標準格式為:(參數(shù)類型 參數(shù)名稱) -> { 代碼語句 }
格式說明: - 小括號內(nèi)的語法與傳統(tǒng)方法參數(shù)列表一致:無參數(shù)則留空;多個參數(shù)則用逗號分隔;
- ->是新引入的語法格式,代表指向動作;
- 大括號內(nèi)的語法與傳統(tǒng)方法體要求基本一致。
練習:使用Lambda標準格式(無參無返回)
給定一個廚子Cooker接口,內(nèi)含唯一的抽象方法makeFood,且無參數(shù)、無返回值。如下:
public interface Cooker {
void makeFood();
}
在下面的代碼中,請使用Lambda的標準格式調(diào)用invokeCook方法,打印輸出“吃飯啦!”字樣:
public class demo01 {
public static void main(String[] args) {
invokeCook(() -> {
System.out.println("吃飯啦!");
});
}
private static void invokeCook(Cooker c){
c.makeFood();
}
}
Lambda的參數(shù)和返回值
需求:使用Lambda表達式對存在數(shù)組中的Person類型的對象數(shù)據(jù)按照年齡的降序輸出。
傳統(tǒng)寫法:
public class Demo02 {
public static void main(String[] args) {
// 本來年齡亂序的對象數(shù)組
Person[] array = {
new Person("古力娜扎", 19),
new Person("迪麗熱巴", 18),
new Person("馬爾扎哈", 20) };
// 匿名內(nèi)部類
Comparator<Person> comp = new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o2.getAge() - o1.getAge();
}
};
Arrays.sort(array, comp); // 第二個參數(shù)為排序規(guī)則,即Comparator接口實例
for (Person person : array) {
System.out.println(person);
}
}
}
Lambda寫法:
public class demo02 {
public static void main(String[] args) {
// 本來年齡亂序的對象數(shù)組
Person[] array = {
new Person("古力娜扎", 19),
new Person("迪麗熱巴", 18),
new Person("馬爾扎哈", 20) };
Arrays.sort(array,(Person p1,Person p2) -> {
return p2.getAge() - p1.getAge();
});
for (Person person : array) {
System.out.println(person);
}
}
}
Lambda省略格式
Lambda強調(diào)的是“做什么”而不是“怎么做”,所以凡是可以根據(jù)上下文推導得知的信息,都可以省略。例如上例還可以使用Lambda的省略寫法:
public static void main(String[] args) {
invokeCalc(120, 130, (a, b) -> a + b);
}
省略規(guī)則:
在Lambda標準格式的基礎(chǔ)上,使用省略寫法的規(guī)則為:
- 小括號內(nèi)參數(shù)的類型可以省略;
- 如果小括號內(nèi)有且僅有一個參數(shù),則小括號可以省略;
- 如果大括號內(nèi)有且僅有一個語句,則無論是否有返回值,都可以省略大括號、return關(guān)鍵字及語句分號。
注意:關(guān)于第三點如果省略一個,那么必須同時都得省略。
2、Lambda表達式的應(yīng)用
Lambda表達式的使用條件是
- 使用lambda表達式的類型必須是一個只含有一個抽象方法的借口
- lambda只能使用final修飾的變量
forEach遍歷Map
//1.forEach遍歷Map
System.out.println("\n1.forEach遍歷Map");
Map<String, Object> map = new HashMap<>();
map.put("key1", 11);
map.put("key2", 12);
map.put("key3", 13);
map.put("key4", 14);
map.forEach((key,value)->{
System.out.println("key:"+key+",value:"+value);
});
輸出:
1.forEach遍歷Map
key:key1,value:11
key:key2,value:12
key:key3,value:13
key:key4,value:14
forEach遍歷List
//2.forEach遍歷List
System.out.println("\n2.forEach遍歷List");
List<Integer> list = new ArrayList<Integer>() ;
list.add(1);
list.add(2);
list.add(3);
list.forEach(value->System.out.println(value));
輸出:
2.forEach遍歷List
1
2
3
在多線程中使用Lambda表達式
//3.在多線程中使用Lambda表達式
System.out.println("\n3.在多線程中使用Lambda表達式");
new Thread(()->System.out.println("new Thread start")).start();
輸出:
3.在多線程中使用Lambda表達式
new Thread start
自定義Lambda表達式功能
//4.自定義Lambda表達式功能
interface MathOperator{
int operator(int a, int b);
}
public static void calc(int a ,int b, MathOperator operator){
System.out.println(operator.operator(a, b));
}
System.out.println("\n4.自定義Lambda表達式功能");
MathOperator add = (a,b)->a+b ;
MathOperator sub = (a,b)->a-b ;
MathOperator mul = (a,b)->a*b ;
MathOperator div = (a,b)->a/b ;
calc(3, 5, add);
calc(3, 5, sub);
calc(3, 5, mul);
calc(3, 5, div);
輸出:
4.自定義Lambda表達式功能
8
-2
15
0
Predicate接口實現(xiàn)數(shù)據(jù)過濾
System.out.println("\n5.Predicate接口實現(xiàn)數(shù)據(jù)過濾");
List<String> filterList = new LinkedList<>() ;
filterList.add("1");
filterList.add("abc");
filterList.add("java");
filterList.add("python2");
filterList.add("python3");
filterList.add("c++");
filture(filterList, str->str.startsWith("j")) ;
//單條件過濾
filterList.stream().filter(str->str.contains("++")).forEach(value->System.out.println(value)) ;
//多條件邏輯過濾
Predicate<String> startWith = str->str.startsWith("p") ;
filterList.stream().filter(startWith.and(str->str.contains("2"))).forEach(value->System.out.println(value)) ;
輸出:
5.Predicate接口實現(xiàn)數(shù)據(jù)過濾
java
c++
python2
Lambda的map和reduce操作
/3.在多線程中使用Lambda表達式
System.out.println("\n6.Lambda的map和reduce操作");
List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
//map操作讓每一個元素加上它之前的0.12倍
costBeforeTax.stream().map(cost -> cost+0.12*cost).forEach(System.out::println);
System.out.println(costBeforeTax.stream().reduce((sum,cost)->sum+cost).get()); //求和
輸出:
6.Lambda的map和reduce操作
112.0
224.0
336.0
448.0
560.0
1500
創(chuàng)建一個字符串列表,每個字符串長度大于2
System.out.println("\n7.創(chuàng)建一個字符串列表,每個字符串長度大于2");
List<String> strList = Arrays.asList(new String[]{"abc","de","abcde"});
List<String> filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
System.out.printf("Original List : %s, filtered list : %s %n", strList, filtered);
輸出:
7.創(chuàng)建一個字符串列表,每個字符串長度大于2
Original List : [abc, de, abcde], filtered list : [abc, abcde]
獲取數(shù)字的個數(shù)、最小值、最大值、總和以及平均值
System.out.println("\n8.獲取數(shù)字的個數(shù)、最小值、最大值、總和以及平均值");
List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Highest prime number in List : " + stats.getMax());
System.out.println("Lowest prime number in List : " + stats.getMin());
System.out.println("Sum of all prime numbers : " + stats.getSum());
System.out.println("Average of all prime numbers : " + stats.getAverage());
輸出:
8.獲取數(shù)字的個數(shù)、最小值、最大值、總和以及平均值
Highest prime number in List : 29
Lowest prime number in List : 2
Sum of all prime numbers : 129
Average of all prime numbers : 12.9