java Lambda表达式详解
文章目錄
- 一、背景
- 1.1語法
- 1.2函數式接口
- 二、Lambda的基本使用
- 2.1引子
- 2.2常見的使用方式
- 2.3語法小結
- 三、變量捕獲
- 3.1 匿名內部類
- 3.2 匿名內部類的變量捕獲
- 3.3Lambda的變量捕獲
- 四、Lambda在集合當中的使用
- 4.1 Collection接口
- 4.2 list接口
- 4.3 Map接口
- 總結
提示:以下是本篇文章正文內容,下面案例可供參考
一、背景
Lambda表達式是Java SE 8中一個重要的新特性。lambda表達式允許你通過表達式來代替功能接口。 lambda表達式就和方法一樣,它提供了一個正常的參數列表和一個使用這些參數的主體(body,可以是一個表達式或一個代碼塊)。 Lambda 表達式(Lambda expression)可以看作是一個匿名函數,基于數學中的λ演算得名,也可稱為閉包(Closure) 。
換句簡單的話說: Lambda表達式允許你直接把一個代碼塊賦值給一個變量
1.1語法
基本語法: (參數) ->表達式 或 (參數) ->{ 語句; }
// 1. 不需要參數,返回值為 2 () -> 2 // 2. 接收一個參數(數字類型),返回其2倍的值 x -> 2 * x // 3. 接受2個參數(數字),并返回他們的和 (x, y) -> x + y // 4. 接收2個int型整數,返回他們的乘積 (int x, int y) -> x * y//可以加類型 // 5. 接受一個 string 對象,并在控制臺打印,不返回任何值(看起來像是返回void) (String s) -> System.out.print(s)1.2函數式接口
要了解Lambda表達式,首先需要了解什么是函數式接口,函數式接口定義:一個接口有且只有一個抽象方法 。
定義方式:
法1:
@FunctionalInterface interface NoParameterNoReturn {//注意:只能有一個方法void test(); }法2:
@FunctionalInterface interface NoParameterNoReturn {void test();default void test2() {System.out.println("JDK1.8新特性,default默認方法可以有具體的實現");} }二、Lambda的基本使用
2.1引子
代碼如下(示例):
//函數式接口 interface NoParameterNoReturn {//注意:只能有一個方法void test(); }public class TestDemo {public static void main(String[] args) {new NoParameterNoReturn(){@Overridepublic void test(){System.out.println("這里是重寫后的方法");}};} }上面這種寫法就相當于有一個類,這個類實現了我們的NoParameterNoReturn 接口,并且重寫了我們的test方法
我們可以把上面代碼塊賦值給NoParameterNoReturn創建的變量parameterNoReturn,并且可以通過parameterNoReturn.test()來調用方法
//函數式接口 interface NoParameterNoReturn {//注意:只能有一個方法void test(); }public class TestDemo {public static void main(String[] args) {NoParameterNoReturn parameterNoReturn=new NoParameterNoReturn(){@Overridepublic void test(){System.out.println("這里是重寫后的方法");}};parameterNoReturn.test();} }但是上面的代碼還是略顯麻煩,我們現在結束Lambda表達式的寫法:
public static void main(String[] args) {NoParameterNoReturn parameterNoReturn=()-> System.out.println("這里是重寫后的方法");parameterNoReturn.test();}我們用()表示沒有參數的匿名函數,后面的方法體就是一個打印語句,兩種寫法運行結果一樣,但是代碼量卻完全不同。
運行結果如下:
2.2常見的使用方式
代碼如下(示例):
//無返回值無參數 @FunctionalInterface interface NoParameterNoReturn {void test(); } //無返回值一個參數 @FunctionalInterface interface OneParameterNoReturn {void test(int a); } //無返回值多個參數 @FunctionalInterface interface MoreParameterNoReturn {void test(int a,int b); } //有返回值無參數 @FunctionalInterface interface NoParameterReturn {int test(); }//有返回值一個參數 @FunctionalInterface interface OneParameterReturn {int test(int a); } //有返回值多參數 @FunctionalInterface interface MoreParameterReturn {int test(int a,int b); }我們在上面提到過,Lambda表達式本質是一個匿名函數,函數的方法是:返回值 方法名 參數列表 方法體。在,Lambda表達式中我們只需要關心:參數列表 方法體。
使用示例:
public static void main(String[] args) {//無返回值無參數NoParameterNoReturn parameterNoReturn=()-> System.out.println("這里是重寫后的方法");parameterNoReturn.test();//無返回值一個參數//寫法1OneParameterNoReturn oneParameterNoReturn=(a)->{System.out.println(a);};oneParameterNoReturn.test(1);//打印1//寫法2OneParameterNoReturn oneParameterNoReturn1=a->System.out.println(a);//只有一個參數,小括號可以省略;只有一條語句,花括號可以省略oneParameterNoReturn1.test(1);//打印1//無返回值多個參數MoreParameterNoReturn moreParameterNoReturn=(a,b)->{System.out.println(a+b);};//這里語句也是一條,如果你想,也可以把花括號去掉,原理同上moreParameterNoReturn.test(1,2);//打印3//有返回值無參數NoParameterReturn noParameterReturn=()->{return 520;};//ps:return不寫也是效果一樣的int ret=noParameterReturn.test();System.out.println(ret);//打印520//有返回值一個參數OneParameterReturn oneParameterReturn=(a)->{return a+1;};//花括號內只要是一個返回式子就行,你甚至可以不帶上a(不用傳過來的參數)int ret1=oneParameterReturn.test(9);System.out.println(ret1);//打印10//有返回值多參數MoreParameterReturn moreParameterReturn=(a,b)->a*b;//相當于(a+b)->{return a*b;}int ret2=moreParameterReturn.test(3,8);System.out.println(ret2);//打印24}2.3語法小結
三、變量捕獲
Lambda 表達式中存在變量捕獲 ,了解了變量捕獲之后,我們才能更好的理解Lambda 表達式的作用域 。Java當中的匿名類中,會存在變量捕獲。
3.1 匿名內部類
匿名內部類就是沒有名字的內部類 。我們這里只是為了說明變量捕獲,所以,匿名內部類只做簡單介紹,下面是匿名內部類的簡單使用方法:
class Test {public void func(){System.out.println("func()");} } public class TestDemo {public static void main(String[] args) {new Test(){@Overridepublic void func() {System.out.println("我是內部類,且重寫了func這個方法!");}};} }3.2 匿名內部類的變量捕獲
如下圖,我們簡單寫了一個匿名內部類,并且嘗試捕獲main函數中的變量a
運行結果如下:
我們對a進行一下修改,看能不能正常捕獲?
發現這里報錯了,因此,我們得知:
在匿名內部類中,捕獲外部的變量前提是——該變量沒有發生修改,或該變量本身是個常量,
3.3Lambda的變量捕獲
如下圖,我們使用一個參數無返回值的Lambda表達式進行示例:
可以正常運行,并打印2 1
那如果我們對x進行一下修改呢?
我們發現,同3.2一樣,如果對變量修改就會報錯
四、Lambda在集合當中的使用
為了能夠讓Lambda和Java的集合類集更好的一起使用,集合當中,也新增了部分接口,以便與Lambda表達式對接。(這里只舉一些常用的)
4.1 Collection接口
forEach( )方法演示:
public static void main(String[] args) {ArrayList<String>list=new ArrayList<>();list.add("a");list.add("bc");list.add("def");list.add("hello");//寫法1:(不用Lambda表達式)list.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});//寫法2:(用Lambda表達式)list.forEach(s-> System.out.println(s));//效果和寫法1一樣}運行結果如下:
4.2 list接口
sort()方法的演示
public static void main(String[] args) {ArrayList<String>list=new ArrayList<>();list.add("hh");list.add("hi");list.add("def");list.add("abc");//寫法1:(不用Lambda表達式)list.sort(new Comparator<String>() {@Overridepublic int compare(String o1,String o2) {return o1.compareTo(o2);}});list.forEach(s-> System.out.println(s));System.out.println("======分割線======");//寫法2:(用Lambda表達式)list.sort(((o1, o2) -> o1.compareTo(o2)));//效果和寫法1一樣list.forEach(s-> System.out.println(s));}//Lambda表達式可以大大縮短代碼量,但是相應的可讀性比較差運行結果如下:
4.3 Map接口
HashMap 的 forEach()
public static void main(String[] args) {HashMap<Integer,String>map=new HashMap<>();map.put(1,"hello");map.put(2,"I");map.put(3,"love");map.put(4,"china");//法一:(不用Lambda)map.forEach(new BiConsumer<Integer, String>() {@Overridepublic void accept(Integer integer, String s) {System.out.println("key:"+integer+"value:"+s);}});System.out.println("======分割線======");//法二:(用Lambda)map.forEach((key,value)-> System.out.println("key:"+key+"value:"+value));}運行結果如下:
總結
Lambda表達式的優點很明顯,在代碼層次上來說,使代碼變得非常的簡潔。缺點也很明顯,代碼不易讀。
優點:
缺點:
總結
以上是生活随笔為你收集整理的java Lambda表达式详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux man命令后数字含义
- 下一篇: 任务间同步 | 信号量、互斥量和事件集