Java Lambda表達(dá)式詳解
Java Lambda表達(dá)式是JDK8引入的,是一個比較重要的特性
Lambda表達(dá)式簡介
Lambda 表達(dá)式是 JDK8 的一個新特性,也被稱為閉包,Lambda表達(dá)式允許把函數(shù)作為一個方法的參數(shù),即行為參數(shù)化,函數(shù)作為參數(shù)傳遞進方法中。
Lambda表達(dá)式可以取代大部分的匿名內(nèi)部類,寫出更優(yōu)雅的 Java 代碼,尤其在集合的遍歷和其他集合操作中,可以極大地優(yōu)化代碼結(jié)構(gòu)。
Lambda表達(dá)式的作用
Java 8 引入的 Lambda表達(dá)式的主要作用就是簡化代碼,寫出更優(yōu)雅的代碼。
怎么一個簡化優(yōu)雅呢,舉一Lambda語法創(chuàng)建線程和匿名內(nèi)部類創(chuàng)建線程的例子,就非常清楚了。
1.匿名類創(chuàng)建線程
// JDK7匿名內(nèi)部類寫法 new Thread(new Runnable() {//接口名 ????????@Override ????????public void run() {//方法名 ????????????System.out.println("mikechen"); ????????} ????});
2.Lambda表達(dá)式創(chuàng)建線程
// JDK8 Lambda來創(chuàng)建線程 new Thread(() -> System.out.println("mikechen"));
上述代碼跟匿名內(nèi)部類的作用是一樣的,但比匿名內(nèi)部類更進一步,這里連接口名和函數(shù)名都一同省掉了,Lambda表達(dá)式可以取代匿名內(nèi)部類,寫出更優(yōu)雅的代碼。
Lambda表達(dá)式的語法
lambda 表達(dá)式的語法格式如下:
- ():左側(cè)部分指定了Lambda表達(dá)式需要的所有參數(shù)。
- ->:Lambda表達(dá)式的操作符或者箭頭操作符。
- {}:右側(cè)部分指定了Lambda體,即方法需要實現(xiàn)的內(nèi)容。
1.無參數(shù)
Lambda體只有一條語句:
示例:
()?->?System.out.println("mikechen");
請注意,括號中沒有內(nèi)容。那就是表示lambda不帶任何參數(shù)。
2.一個參數(shù)
示例:
Consumer<String> con = (x) -> System.out.println(x);
當(dāng)lambda表達(dá)式是單個參數(shù)時,也可以省略括號,如下所示:
Consumer<String> con = x -> System.out.println(x);
3.多個參數(shù)
如果Java lambda表達(dá)式匹配的方法有多個參數(shù),則需要在括號內(nèi)列出這些參數(shù),代碼如下:
BinaryOperator<Integer> bo = (a, b) -> { System.out.println("函數(shù)式接口"); return a + b; };
注意:僅當(dāng)方法是單個參數(shù)時,才可以省略括號。
4.指定參數(shù)類型
如果編譯器無法從lambda匹配的函數(shù)式接口抽象方法推斷參數(shù)類型,則有時可能需要為lambda表達(dá)式指定參數(shù)類型。
(Car car) -> System.out.println("The car is: " + car.getName());
如你所見,car參數(shù)的類型(Car)寫在參數(shù)名稱的前面,就像在其他方法中聲明參數(shù)或?qū)涌谶M行匿名實現(xiàn)時一樣。
5.只有一條語句時
當(dāng)Lambda體只有一條語句時,return和大括號可以省略,示例:
BinaryOperator<Integer> bo = (a, b) -> a + b;
6.參數(shù)類型不寫
Lambda表達(dá)式的參數(shù)列表的數(shù)據(jù)類型可以省略不寫,因為JVM編譯器能夠通過上下文推斷出數(shù)據(jù)類型,這就是“類型推斷”,示例:
BinaryOperator<Integer> bo = (Integer a, Integer b) -> { return a + b; };
等同于
BinaryOperator<Integer> bo = (a, b) -> { return a + b; };
上述 Lambda 表達(dá)式中的參數(shù)類型都是由編譯器推斷得出,Lambda 表達(dá)式中無需指定類型,程序依然可以編譯,這是因為 javac 根據(jù)程序的上下文,在后臺推斷出了參數(shù)的類型。
Lambda 表達(dá)式的類型依賴于上下文環(huán)境,是由編譯器推斷出來的,這就是所謂的“類型推斷”。
7.Lambda表達(dá)式返回值
你可以從Java lambda表達(dá)式返回值,就像從方法中返回值一樣。你只需向lambda表達(dá)式主體添加一個return,如下所示:
(param) -> { System.out.println("param: " + param); return "return value"; }
函數(shù)式接口
Lambda表達(dá)式需要函數(shù)式接口的支持,所以,我們有必要來說說什么是函數(shù)式接口。
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface FunctionalInterface {}
一種用于表示一個接口是Java語言規(guī)范定義的函數(shù)式接口的注解類型。
對于函數(shù)式接口,我們可以理解為只有一個抽象方法的接口,除此之外它和別的接口相比并沒有什么特殊的地方。
public interface MyFunctionInterface<T> { public T getValue(T t); }
為了確保函數(shù)式接口的正確性,我們可以給這個接口添加@FunctionalInterface注解,這樣當(dāng)其中有超過一個抽象方法時就會報錯。
Unexpected @FunctionalInterface annotation @FunctionalInterface ^ WorkerInterface is not a functional interface multiple non-overriding abstract methods found in interface WorkerInterface 1 error
Java 8中每一個Lambda表達(dá)式必須有一個函數(shù)式接口與之對應(yīng),也就是說,只要一個對象是函數(shù)式接口的實例,那么該對象就可以用Lambda表達(dá)式來表示。
Lambda表達(dá)式的舉例
學(xué)習(xí) Lambda 表達(dá)式的最好方式是學(xué)習(xí)例子,下面我們看幾個比較常用的例子。
1.lambda創(chuàng)建線程
使用() -> {} 替代匿名類:
//JDK 8之前 new Thread(new Runnable() { @Override public void run() { System.out.println("使用匿名內(nèi)部類,開線程"); } }).start(); //JDK 8 使用lambda表達(dá)式 new Thread(() -> System.out.println("使用lambda表達(dá)式,開線程")).start();
2.lambda事件處理
使用lambda表達(dá)式如下所示寫出更好的事件偵聽器的代碼:
// Java 8之前: button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("Button被點擊了使用老的方式!"); } }); // Java 8方式: button.addActionListener( (e) -> { System.out.println("Button被點擊了使用Lambda表達(dá)式!"); });
3.lambda遍歷List集合
集合的遍歷,采用lambda表達(dá)式會更簡潔:
// Java 8之前: List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API"); for (String feature : features) { System.out.println(feature); } // Java 8之后: List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API"); features.forEach(n -> System.out.println(n)); // 使用Java 8的方法引用更方便,方法引用由::雙冒號操作符標(biāo)示, features.forEach(System.out::println);
方法引用是使用兩個冒號::這個操作符號。
4.元素排序
之前我們?nèi)粢獮榧蟽?nèi)的元素排序,就必須調(diào)用 sort 方法,傳入比較器重寫 compare。
方法的比較器對象,現(xiàn)在我們還可以使用 lambda 表達(dá)式來簡化代碼。
public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("a"); list.add("d"); list.add("b"); list.add("c"); list.sort((o1,o2)->o1.compareTo(o2)); list.forEach(System.out::println); }
5.lambda Map
// 不使用lambda表達(dá)式為每個訂單加上12%的稅 List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500); for (Integer cost : costBeforeTax) { double price = cost + .12*cost; System.out.println(price); } // 使用lambda表達(dá)式 List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500); costBeforeTax.stream().map((cost) -> cost + .12*cost).forEach(System.out::println);
6.lambda過濾String
// 創(chuàng)建一個字符串列表,每個字符串長度大于2 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.lambda對集合應(yīng)用函數(shù)
// 將字符串換成大寫并用逗號鏈接起來 List<String> G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada"); String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", ")); System.out.println(G7Countries);
8.lambda計算最大值、最小值、平均值
//獲取數(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());
以上就是Java Lambda表達(dá)式詳解的詳細(xì)內(nèi)容,更多關(guān)于Java Lambda表達(dá)式詳解的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Redis 集成Spring的示例代碼(spring-data-redis)
本篇文章主要介紹了Redis 集成Spring的示例代碼(spring-data-redis) ,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09Spring導(dǎo)入properties配置文件代碼示例
這篇文章主要介紹了Spring導(dǎo)入properties配置文件代碼示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10