欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaSE中Lambda表達式的使用與變量捕獲

 更新時間:2023年10月01日 08:26:38   作者:遇事問春風乄  
這篇文章主要介紹了JavaSE中Lambda表達式的使用與變量捕獲,Lambda表達式允許你通過表達式來代替功能接口, 就和方法一樣,它提供了一個正常的參數(shù)列表和一個使用這些參數(shù)的主體,下面我們來詳細看看,需要的朋友可以參考下

Lambda表達式的背景

Lambda表達式是Java SE 8中一個重要的新特性。lambda表達式允許你通過表達式來代替功能接口。 lambda表達式就和方法一樣,它提供了一個正常的參數(shù)列表和一個使用這些參數(shù)的主體(body,可以是一個表達式或一個代碼塊)。 Lambda 表達式(Lambda expression),基于數(shù)學中的λ演算得名,也可稱為閉包(Closure) 。

Lambda表達式的語法

基本語法: (parameters) -> expression 或 (parameters) ->{ statements; }

Lambda表達式由三部分組成:

paramaters:類似方法中的形參列表,這里的參數(shù)是函數(shù)式接口里的參數(shù)。這里的參數(shù)類型可以明確的聲明也可不聲明而由JVM隱含的推斷。另外當只有一個推斷類型時可以省略掉圓括號。

->:可理解為“被用于”的意思

方法體:可以是表達式也可以代碼塊,是函數(shù)式接口里方法的實現(xiàn)。代碼塊可返回一個值或者什么都不反回,這里的代碼塊塊等同于方法的方法體。如果是表達式,也可以返回一個值或者什么都不反回。

示例如下:

// 1. 不需要參數(shù),返回值為 2
() -> 2
// 2. 接收一個參數(shù)(數(shù)字類型),返回其2倍的值
x -> 2 * x
// 3. 接受2個參數(shù)(數(shù)字),并返回他們的和
(x, y) -> x + y
// 4. 接收2個int型整數(shù),返回他們的乘積
(int x, int y) -> x * y
// 5. 接受一個 string 對象,并在控制臺打印,不返回任何值(看起來像是返回void)
(String s) -> System.out.print(s)

函數(shù)式接口

要了解Lambda表達式,首先需要了解什么是函數(shù)式接口,函數(shù)式接口定義:一個接口有且只有一個抽象方法

注意:

  • 如果一個接口只有一個抽象方法,那么該接口就是一個函數(shù)式接口
  • 如果我們在某個接口上聲明了 @FunctionalInterface 注解,那么編譯器就會按照函數(shù)式接口的定義來要求該接口,這樣如果有兩個抽象方法,程序編譯就會報錯的。所以,從某種意義上來說,只要你保證你的接口中只有一個抽象方法,你可以不加這個注解。加上就會自動進行檢測的。

定義方式:

@FunctionalInterface
interface NoParameterNoReturn {
	//注意:只能有一個方法
	void test();
}

也提供了另一種方式:

@FunctionalInterface
interface NoParameterNoReturn {
	void test();
	default void test2() {
		System.out.println("JDK1.8新特性,default默認方法可以有具體的實現(xiàn)");
	}
}

Lambda表達式的基本使用

首先,我們實現(xiàn)準備好幾個接口:

//無返回值無參數(shù)
@FunctionalInterface
interface NoParameterNoReturn {
	void test();
} 
//無返回值一個參數(shù)
@FunctionalInterface
interface OneParameterNoReturn {
	void test(int a);
} 
//無返回值多個參數(shù)
@FunctionalInterface
interface MoreParameterNoReturn {
	void test(int a,int b);
} 
//有返回值無參數(shù)
@FunctionalInterface
interface NoParameterReturn {
	int test();
} 
//有返回值一個參數(shù)
@FunctionalInterface
interface OneParameterReturn {
	int test(int a);
} 
//有返回值多參數(shù)
@FunctionalInterface
interface MoreParameterReturn {
	int test(int a,int b);
}

我們在上面提到過,Lambda可以理解為:Lambda就是匿名內(nèi)部類的簡化,實際上是創(chuàng)建了一個類,實現(xiàn)了接口,重寫了接口的方法 。

沒有使用lambda表達式的時候的調(diào)用方式 :

NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn(){
@Override
public void test() {
	System.out.println("hello");
	}
};
noParameterNoReturn.test();

具體使用見以下示例代碼:

public class TestDemo {
    public static void main(String[] args) {
        NoParameterNoReturn noParameterNoReturn = ()->{
            System.out.println("無參數(shù)無返回值");
        };
        noParameterNoReturn.test();
        OneParameterNoReturn oneParameterNoReturn = (int a)->{
            System.out.println("一個參數(shù)無返回值:"+ a);
        };
        oneParameterNoReturn.test(10);
        MoreParameterNoReturn moreParameterNoReturn = (int a,int b)->{
            System.out.println("多個參數(shù)無返回值:"+a+" "+b);
        };
        moreParameterNoReturn.test(20,30);
        NoParameterReturn noParameterReturn = ()->{
            System.out.println("有返回值無參數(shù)!");
            return 40;
        };
//接收函數(shù)的返回值
        int ret = noParameterReturn.test();
        System.out.println(ret);
        OneParameterReturn oneParameterReturn = (int a)->{
            System.out.println("有返回值有一個參數(shù)!");
            return a;
        };
        ret = oneParameterReturn.test(50);
        System.out.println(ret);
        MoreParameterReturn moreParameterReturn = (int a,int b)->{
            System.out.println("有返回值多個參數(shù)!");
            return a+b;
        };
        ret = moreParameterReturn.test(60,70);
        System.out.println(ret);
    }
}

語法精簡

  • 參數(shù)類型可以省略,如果需要省略,每個參數(shù)的類型都要省略。
  • 參數(shù)的小括號里面只有一個參數(shù),那么小括號可以省略
  • 如果方法體當中只有一句代碼,那么大括號可以省略
  • 如果方法體中只有一條語句,且是return語句,那么大括號可以省略,且去掉return關鍵字。

示例代碼:

  public static void main(String[] args) {
        MoreParameterNoReturn moreParameterNoReturn = ( a, b)->{
            System.out.println("無返回值多個參數(shù),省略參數(shù)類型:"+a+" "+b);
        };
        moreParameterNoReturn.test(20,30);
        OneParameterNoReturn oneParameterNoReturn = a ->{
            System.out.println("無參數(shù)一個返回值,小括號可以勝率:"+ a);
        };
        oneParameterNoReturn.test(10);
        NoParameterNoReturn noParameterNoReturn = ()->System.out.println("無參數(shù)無返回值,方法體中只有一行代碼");
        noParameterNoReturn.test();
//方法體中只有一條語句,且是return語句
        NoParameterReturn noParameterReturn = ()-> 40;
        int ret = noParameterReturn.test();
        System.out.println(ret);
    }

變量捕獲

Lambda 表達式中存在變量捕獲 ,了解了變量捕獲之后,我們才能更好的理解Lambda 表達式的作用域 。Java當中的匿名類中,會存在變量捕獲

匿名內(nèi)部類

匿名內(nèi)部類就是沒有名字的內(nèi)部類 。我們這里只是為了說明變量捕獲

匿名內(nèi)部類的簡單的使用如下:

class Test {
    public void func(){
        System.out.println("func()");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        new Test(){
            @Override
            public void func() {
                System.out.println("我是內(nèi)部類,且重寫了func這個方法!");
            }
        };
    }
}

匿名內(nèi)部類的變量捕獲

class Test {
    public void func(){
        System.out.println("func()");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        int a = 100;
        new Test(){
            @Override
            public void func() {
                System.out.println("我是內(nèi)部類,且重寫了func這個方法!");
                System.out.println("我是捕獲到變量 a == "+a
                        +" 我是一個常量,或者是一個沒有改變過值的變量!");
            }
        };
    }
}

在上述代碼當中的變量a就是,捕獲的變量。這個變量要么是被final修飾,如果不是被final修飾的 你要保證在使用之前,沒有修改

Lambda的變量捕獲

在Lambda當中也可以進行變量的捕獲,具體我們看一下代碼:

@FunctionalInterface
interface NoParameterNoReturn {
    void test();
}
    public static void main(String[] args) {
        int a = 10;
        NoParameterNoReturn noParameterNoReturn = ()->{
// a = 99; error
            System.out.println("捕獲變量:"+a);
        };
        noParameterNoReturn.test();
    }

Lambda在集合當中的使用

為了能夠讓Lambda和Java的集合類集更好的一起使用,集合當中,也新增了部分接口,以便與Lambda表達式對接

注意:Collection的forEach()方法是從接口 java.lang.Iterable 拿過來的。

Collection接口

forEach() 方法演示

該方法在接口 Iterable 當中,原型如下

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

該方法表示:對容器中的每個元素執(zhí)行action指定的動作 。

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Hello");
        list.add("腳本之家");
        list.add("hello");
        list.add("網(wǎng)站");
        list.forEach(new Consumer<String>(){
            @Override
            public void accept(String str){
//簡單遍歷集合中的元素。
                System.out.print(str+" ");
            }
        });

輸出結果:Hello 腳本之家 hello 網(wǎng)站

我們可以修改為如下代碼:

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Hello");
        list.add("腳本之家");
        list.add("hello");
        list.add("網(wǎng)站");
//表示調(diào)用一個,不帶有參數(shù)的方法,其執(zhí)行花括號內(nèi)的語句,為原來的函數(shù)體內(nèi)容。
        list.forEach(s -> {
            System.out.println(s);
        });
    }

輸出結果:Hello 腳本之家 hello 網(wǎng)站

List接口

sort()方法的演示

sort方法源碼:該方法根據(jù)c指定的比較規(guī)則對容器元素進行排序。

public void sort(Comparator<? super E> c) {
	final int expectedModCount = modCount;
	Arrays.sort((E[]) elementData, 0, size, c);
	if (modCount != expectedModCount) {
		throw new ConcurrentModificationException();
	}
	modCount++;
}

使用示例:

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Hello");
        list.add("腳本之家");
        list.add("hello");
        list.add("網(wǎng)站");
        list.sort(new Comparator<String>() {
            @Override
            public int compare(String str1, String str2){
//注意這里比較長度
                return str1.length()-str2.length();
            }
        });
        System.out.println(list);
    }

輸出結果:腳本之家, Hello, hello, 網(wǎng)站

修改為lambda表達式:

public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
    list.add("Hello");
    list.add("腳本之家");
    list.add("hello");
    list.add("網(wǎng)站");
	//調(diào)用帶有2個參數(shù)的方法,且返回長度的差值
	list.sort((str1,str2)-> str1.length()-str2.length());
	System.out.println(list);
}

輸出結果:腳本之家, Hello, hello, 網(wǎng)站

Map接口

HashMap 的 forEach()

該方法原型如下:

default void forEach(BiConsumer<? super K, ? super V> action) {Objects.requireNonNull(action);
    for (Map.Entry<K, V> entry : entrySet()) {
        K k;
        V v;
        try {
            k = entry.getKey();
            v = entry.getValue();
        } catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
            throw new ConcurrentModificationException(ise);
        } 
        action.accept(k, v);
    }
}

作用是對Map中的每個映射執(zhí)行action指定的操作。

代碼示例:

public static void main(String[] args) {
	HashMap<Integer, String> map = new HashMap<>();
	map.put(1, "hello");
	map.put(2, "腳本之家");
	map.put(3, "hello");
	map.put(4, "網(wǎng)站");
	map.forEach(new BiConsumer<Integer, String>(){
		@Override
		public void accept(Integer k, String v){
			System.out.println(k + "=" + v);
		}
	});
}

輸出結果:

1=hello 2=腳本之家 3=hello 4=網(wǎng)站

使用lambda表達式后的代碼:

public static void main(String[] args) {
	HashMap<Integer, String> map = new HashMap<>();
	map.put(1, "hello");
	map.put(2, "腳本之家");
	map.put(3, "hello");
	map.put(4, "網(wǎng)站");
	map.forEach((k,v)-> System.out.println(k + "=" + v));
}

輸出結果:

1=hello 2=腳本之家 3=hello 4=網(wǎng)站

Lambda表達式總結

Lambda表達式的優(yōu)點很明顯,在代碼層次上來說,使代碼變得非常的簡潔。缺點也很明顯,代碼不易讀。

優(yōu)點:

  • 代碼簡潔,開發(fā)迅速
  • 方便函數(shù)式編程
  • 非常容易進行并行計算
  • Java 引入 Lambda,改善了集合操作

缺點:

  • 代碼可讀性變差
  • 在非并行計算中,很多計算未必有傳統(tǒng)的 for 性能要高
  • 不容易進行調(diào)試

到此這篇關于JavaSE中Lambda表達式的使用與變量捕獲的文章就介紹到這了,更多相關JavaSE Lambda表達式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java httpclient設置超時時間和代理的方法

    java httpclient設置超時時間和代理的方法

    這篇文章主要介紹了java httpclient設置超時時間和代理的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02
  • SpringBoot后端上傳文件類型檢測方式

    SpringBoot后端上傳文件類型檢測方式

    這篇文章主要介紹了SpringBoot后端上傳文件類型檢測方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SpringBoot底層注解超詳細介紹

    SpringBoot底層注解超詳細介紹

    這篇文章主要介紹了SpringBoot底層注解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-09-09
  • 解決Java編譯時錯誤:A JNI error has occurred,please check your installation and try again

    解決Java編譯時錯誤:A JNI error has occurred,ple

    這篇文章主要介紹了解決Java編譯時錯誤:A JNI error has occurred,please check your installation and try again,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • JavaWeb實現(xiàn)文件上傳與下載實例詳解

    JavaWeb實現(xiàn)文件上傳與下載實例詳解

    在Web應用程序開發(fā)中,文件上傳與下載功能是非常常用的功能,下面通過本文給大家介紹JavaWeb實現(xiàn)文件上傳與下載實例詳解,對javaweb文件上傳下載相關知識感興趣的朋友一起學習吧
    2016-02-02
  • Java接口的本質(zhì)解析

    Java接口的本質(zhì)解析

    Java接口是初學者必須經(jīng)歷的基礎,但初學之時肯定不會完全懂,溫故而知新本篇文章就帶你重拾接口全面掌握
    2022-03-03
  • 五分鐘帶你學會用java解析json字符串

    五分鐘帶你學會用java解析json字符串

    這篇文章主要給大家介紹了關于用java解析json字符串的相關資料,JSON是一種輕量級的、基于文本的、與語言無關的數(shù)據(jù)交換格式,易于人和機器讀寫,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • Idea中springboot項目的熱部署無法生效問題解決

    Idea中springboot項目的熱部署無法生效問題解決

    本文主要介紹了Idea中springboot項目的熱部署無法生效問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-10-10
  • 使用MyBatis-Plus實現(xiàn)聯(lián)表查詢分頁的示例代碼

    使用MyBatis-Plus實現(xiàn)聯(lián)表查詢分頁的示例代碼

    本文主要講述了如何在SpringBoot項目中使用MyBatis-Plus的分頁插件,通過這個示例,可以學會如何利用MyBatis-Plus進行高效的分頁查詢,感興趣的可以了解一下
    2024-10-10
  • mybatis mapper.xml獲取insert后的自增ID問題

    mybatis mapper.xml獲取insert后的自增ID問題

    這篇文章主要介紹了mybatis mapper.xml獲取insert后的自增ID問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05

最新評論