最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java8深入學(xué)習(xí)系列(一)lambda表達(dá)式介紹

 更新時(shí)間:2017年08月09日 10:14:18   作者:王爵nice  
Java8最值得學(xué)習(xí)的特性就是Lambda表達(dá)式和Stream API,所以我們學(xué)習(xí)java8的第一課就是學(xué)習(xí)lambda表達(dá)式,下面這篇文章主要給大家介紹了關(guān)于Java8學(xué)習(xí)之lambda的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。

前言

最近在學(xué)習(xí)java8,所以接下來會(huì)給大家介紹一系列的Java8學(xué)習(xí)內(nèi)容,那么讓我們先從lambda表達(dá)式開始。

眾所周知從java8出現(xiàn)以來lambda是最重要的特性之一,它可以讓我們用簡(jiǎn)潔流暢的代碼完成一個(gè)功能。 很長(zhǎng)一段時(shí)間java被吐槽是冗余和缺乏函數(shù)式編程能力的語(yǔ)言,隨著函數(shù)式編程的流行java8種也引入了 這種編程風(fēng)格。在此之前我們都在寫匿名內(nèi)部類干這些事,但有時(shí)候這不是好的做法,本文中將介紹和使用lambda, 帶你體驗(yàn)函數(shù)式編程的魔力。


什么是lambda?

lambda表達(dá)式是一段可以傳遞的代碼,它的核心思想是將面向?qū)ο笾械膫鬟f數(shù)據(jù)變成傳遞行為。 我們回顧一下在使用java8之前要做的事,之前我們編寫一個(gè)線程時(shí)是這樣的:

Runnable r = new Runnable() {
 @Override
 public void run() {
 System.out.println("do something."); 
 }
}

也有人會(huì)寫一個(gè)類去實(shí)現(xiàn)Runnable接口,這樣做沒有問題,我們注意這個(gè)接口中只有一個(gè)run方法, 當(dāng)把Runnable對(duì)象給Thread對(duì)象作為構(gòu)造參數(shù)時(shí)創(chuàng)建一個(gè)線程,運(yùn)行后將輸出do something. 。 我們使用匿名內(nèi)部類的方式實(shí)現(xiàn)了該方法。

這實(shí)際上是一個(gè)代碼即數(shù)據(jù)的例子,在run方法中是線程要執(zhí)行的一個(gè)任務(wù),但上面的代碼中任務(wù)內(nèi)容已經(jīng)被規(guī)定死了。 當(dāng)我們有多個(gè)不同的任務(wù)時(shí),需要重復(fù)編寫如上代碼。

設(shè)計(jì)匿名內(nèi)部類的目的,就是為了方便 Java 程序員將代碼作為數(shù)據(jù)傳遞。不過,匿名內(nèi)部 類還是不夠簡(jiǎn)便。 為了執(zhí)行一個(gè)簡(jiǎn)單的任務(wù)邏輯,不得不加上 6 行冗繁的樣板代碼。那如果是lambda該怎么做?

Runnable r = () -> System.out.println("do something.");

嗯,這代碼看起來很酷,你可以看到我們用()和->的方式完成了這件事,這是一個(gè)沒有名字的函數(shù),也沒有人和參數(shù),再簡(jiǎn)單不過了。 使用->將參數(shù)和實(shí)現(xiàn)邏輯分離,當(dāng)運(yùn)行這個(gè)線程的時(shí)候執(zhí)行的是->之后的代碼片段,且編譯器幫助我們做了類型推導(dǎo); 這個(gè)代碼片段可以是用{}包含的一段邏輯。下面一起來學(xué)習(xí)一下lambda的語(yǔ)法。

基礎(chǔ)語(yǔ)法

在lambda中我們遵循如下的表達(dá)式來編寫:

expression = (variable) -> action
  • variable: 這是一個(gè)變量,一個(gè)占位符。像x,y,z,可以是多個(gè)變量。
  • action: 這里我稱它為action, 這是我們實(shí)現(xiàn)的代碼邏輯部分,它可以是一行代碼也可以是一個(gè)代碼片段

可以看到Java中l(wèi)ambda表達(dá)式的格式:參數(shù)、箭頭、以及動(dòng)作實(shí)現(xiàn),當(dāng)一個(gè)動(dòng)作實(shí)現(xiàn)無法用一行代碼完成,可以編寫 一段代碼用{}包裹起來。

lambda表達(dá)式可以包含多個(gè)參數(shù),例如:

int sum = (x, y) -> x + y;

這時(shí)候我們應(yīng)該思考這段代碼不是之前的x和y數(shù)字相加,而是創(chuàng)建了一個(gè)函數(shù),用來計(jì)算兩個(gè)操作數(shù)的和。 后面用int類型進(jìn)行接收,在lambda中為我們省略去了return。

函數(shù)式接口

函數(shù)式接口是只有一個(gè)方法的接口,用作lambda表達(dá)式的類型。前面寫的例子就是一個(gè)函數(shù)式接口,來看看jdk中的Runnable源碼

@FunctionalInterface
public interface Runnable {
 /**
 * When an object implementing interface <code>Runnable</code> is used
 * to create a thread, starting the thread causes the object's
 * <code>run</code> method to be called in that separately executing
 * thread.
 * <p>
 * The general contract of the method <code>run</code> is that it may
 * take any action whatsoever.
 *
 * @see java.lang.Thread#run()
 */
 public abstract void run();
}

這里只有一個(gè)抽象方法run,實(shí)際上你不寫public abstract也是可以的,在接口中定義的方法都是public abstract的。 同時(shí)也使用注解@FunctionalInterface告訴編譯器這是一個(gè)函數(shù)式接口,當(dāng)然你不這么寫也可以,標(biāo)識(shí)后明確了這個(gè)函數(shù)中 只有一個(gè)抽象方法,當(dāng)你嘗試在接口中編寫多個(gè)方法的時(shí)候編譯器將不允許這么干。

嘗試函數(shù)式接口

我們來編寫一個(gè)函數(shù)式接口,輸入一個(gè)年齡,判斷這個(gè)人是否是成人。

public class FunctionInterfaceDemo {
 @FunctionalInterface
 interface Predicate<T> {
 boolean test(T t);
 }
 /**
 * 執(zhí)行Predicate判斷
 *
 * @param age 年齡
 * @param predicate Predicate函數(shù)式接口
 * @return  返回布爾類型結(jié)果
 */
 public static boolean doPredicate(int age, Predicate<Integer> predicate) {
 return predicate.test(age);
 }
 
 public static void main(String[] args) {
 boolean isAdult = doPredicate(20, x -> x >= 18);
 System.out.println(isAdult);
 }
}

從這個(gè)例子我們很輕松的完成 是否是成人 的動(dòng)作,其次判斷是否是成人,在此之前我們的做法一般是編寫一個(gè) 判斷是否是成人的方法,是無法將 判斷 共用的。而在本例只,你要做的是將 行為 (判斷是否是成人,或者是判斷是否大于30歲) 傳遞進(jìn)去,函數(shù)式接口告訴你結(jié)果是什么。

實(shí)際上諸如上述例子中的接口,偉大的jdk設(shè)計(jì)者為我們準(zhǔn)備了java.util.function包


我們前面寫的Predicate函數(shù)式接口也是JDK種的一個(gè)實(shí)現(xiàn),他們大致分為以下幾類:

接口 參數(shù) 返回值 類別 示例
Consumer T void 消費(fèi)型接口 輸出一個(gè)值
Supplier None T 供給型接口 工廠方法
Function T R 函數(shù)型接口 獲得 Artist 對(duì)象的名字
Predicate T boolean 斷言型接口 這張唱片已經(jīng)發(fā)行了嗎

消費(fèi)型接口示例

public static void donation(Integer money, Consumer<Integer> consumer){
 consumer.accept(money); 
}
public static void main(String[] args) {
 donation(1000, money -> System.out.println("好心的麥樂迪為Blade捐贈(zèng)了"+money+"元")) ;
}

供給型接口示例

public static List<Integer> supply(Integer num, Supplier<Integer> supplier){
 List<Integer> resultList = new ArrayList<Integer>() ;
 for(int x=0;x<num;x++) 
  resultList.add(supplier.get());
 return resultList ;
}
public static void main(String[] args) {
 List<Integer> list = supply(10,() -> (int)(Math.random()*100));
 list.forEach(System.out::println);
}

函數(shù)型接口示例

轉(zhuǎn)換字符串為Integer

public static Integer convert(String str, Function<String, Integer> function) {
 return function.apply(str);
}
public static void main(String[] args) {
 Integer value = convert("28", x -> Integer.parseInt(x));
}

斷言型接口示例

篩選出只有2個(gè)字的水果

public static List<String> filter(List<String> fruit, Predicate<String> predicate){
 List<String> f = new ArrayList<>();
 for (String s : fruit) {
 if(predicate.test(s)){
  f.add(s);
 }
 }
 return f;
}
public static void main(String[] args) {
 List<String> fruit = Arrays.asList("香蕉", "哈密瓜", "榴蓮", "火龍果", "水蜜桃");
 List<String> newFruit = filter(fruit, (f) -> f.length() == 2);
 System.out.println(newFruit);
}

默認(rèn)方法

在Java語(yǔ)言中,一個(gè)接口中定義的方法必須由實(shí)現(xiàn)類提供實(shí)現(xiàn)。但是當(dāng)接口中加入新的API時(shí), 實(shí)現(xiàn)類按照約定也要修改實(shí)現(xiàn),而Java8的API對(duì)現(xiàn)有接口也添加了很多方法,比如List接口中添加了sort方法。 如果按照之前的做法,那么所有的實(shí)現(xiàn)類都要實(shí)現(xiàn)sort方法,JDK的編寫者們一定非常抓狂。

幸運(yùn)的是我們使用了Java8,這一問題將得到很好的解決,在Java8種引入新的機(jī)制,支持在接口中聲明方法同時(shí)提供實(shí)現(xiàn)。 這令人激動(dòng)不已,你有兩種方式完成 1.在接口內(nèi)聲明靜態(tài)方法 2.指定一個(gè)默認(rèn)方法。

我們來看看在JDK8中上述List接口添加方法的問題是如何解決的

default void sort(Comparator<? super E> c) {
 Object[] a = this.toArray();
 Arrays.sort(a, (Comparator) c);
 ListIterator<E> i = this.listIterator();
 for (Object e : a) {
 i.next();
 i.set((E) e);
 }
}

翻閱List接口的源碼,其中加入一個(gè)默認(rèn)方法default void sort(Comparator<? super E> c) 。 在返回值之前加入default關(guān)鍵字,有了這個(gè)方法我們可以直接調(diào)用sort方法進(jìn)行排序。

List<Integer> list = Arrays.asList(2, 7, 3, 1, 8, 6, 4);
list.sort(Comparator.naturalOrder());
System.out.println(list);

Comparator.naturalOrder()是一個(gè)自然排序的實(shí)現(xiàn),這里可以自定義排序方案。 你經(jīng)??吹绞褂肑ava8操作集合的時(shí)候可以直接foreach的原因也是在Iterable接口中也新增了一個(gè)默認(rèn)方法:forEach , 該方法功能和 for 循環(huán)類似,但是允許 用戶使用一個(gè)Lambda表達(dá)式作為循環(huán)體。

在后面的章節(jié)中我們?cè)俅瓮ㄟ^案例來展示函數(shù)式編程的魅力 :)

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • springboot rabbitmq整合rabbitmq之消息持久化存儲(chǔ)問題

    springboot rabbitmq整合rabbitmq之消息持久化存儲(chǔ)問題

    這篇文章主要介紹了springboot rabbitmq整合rabbitmq之消息持久化存儲(chǔ)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • java使用CompletableFuture分批處理任務(wù)實(shí)現(xiàn)

    java使用CompletableFuture分批處理任務(wù)實(shí)現(xiàn)

    本文主要介紹了java使用CompletableFuture分批處理任務(wù)實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • springboot?maven?plugin報(bào)紅的解決辦法

    springboot?maven?plugin報(bào)紅的解決辦法

    本文主要介紹了springboot?maven?plugin報(bào)紅的解決辦法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • 利用Java自寫一個(gè)生成ID的工具類

    利用Java自寫一個(gè)生成ID的工具類

    平時(shí)項(xiàng)目中只要涉及表,那么一定能接觸到眾多各式各樣的ID編號(hào)。本文將通過Java語(yǔ)言實(shí)現(xiàn)手寫一個(gè)ID生成工具類,需要的小伙伴可以參考一下
    2022-11-11
  • 深入理解Maven的坐標(biāo)與依賴

    深入理解Maven的坐標(biāo)與依賴

    這篇文章主要介紹了深入理解Maven的坐標(biāo)與依賴,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-01-01
  • Spring Cloud之服務(wù)監(jiān)控turbine的示例

    Spring Cloud之服務(wù)監(jiān)控turbine的示例

    這篇文章主要介紹了Spring Cloud之服務(wù)監(jiān)控turbine的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • jar包打包成exe安裝包的實(shí)現(xiàn)

    jar包打包成exe安裝包的實(shí)現(xiàn)

    本文主要介紹了jar包打包成exe安裝包的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • java如何調(diào)用kettle設(shè)置變量和參數(shù)

    java如何調(diào)用kettle設(shè)置變量和參數(shù)

    文章簡(jiǎn)要介紹了如何在Java中調(diào)用Kettle,并重點(diǎn)討論了變量和參數(shù)的區(qū)別,以及在Java代碼中如何正確設(shè)置和使用這些變量,避免覆蓋Kettle中已設(shè)置的變量,作者分享了個(gè)人經(jīng)驗(yàn),并鼓勵(lì)大家參考和使用腳本之家
    2025-01-01
  • Springboot+MybatisPlus實(shí)現(xiàn)帶驗(yàn)證碼的登錄

    Springboot+MybatisPlus實(shí)現(xiàn)帶驗(yàn)證碼的登錄

    本文主要介紹了Springboot+MybatisPlus實(shí)現(xiàn)帶驗(yàn)證碼的登錄,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • Java后端用EL表達(dá)式改進(jìn)JSP

    Java后端用EL表達(dá)式改進(jìn)JSP

    EL 全名為Expression Language,EL的語(yǔ)法很簡(jiǎn)單,它最大的特點(diǎn)就是使用上很方便,本文帶你用EL表達(dá)式改進(jìn)JSP,感興趣的朋友來看看吧
    2022-02-02

最新評(píng)論

宁武县| 玛曲县| 河北省| 老河口市| 绥化市| 罗田县| 从江县| 抚顺市| 紫金县| 孟津县| 托克逊县| 新河县| 堆龙德庆县| 新安县| 黄骅市| 江华| 万州区| 醴陵市| 安达市| 盐亭县| 增城市| 沈阳市| 双柏县| 汝南县| 漾濞| 镇平县| 博客| 宁国市| 新竹市| 宁明县| 平安县| 屯留县| 张家港市| 永川市| 绥德县| 开封市| 清苑县| 如皋市| 高密市| 吴桥县| 隆化县|