日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

提升你的代码——Lambda!

發布時間:2024/4/11 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 提升你的代码——Lambda! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。

歡迎跳轉到本文的原文鏈接:https://honeypps.com/java/java-lambda-quick-start/


前言

上個月(2018年2月)看過一份調研報告,對于Java版本而言,生產環境中用的最多的是JDk6和JDK7,雖然JDK8在自2014年3月發布至今使用占比仍然很小,想想月底JDK10都要出來了呀。JDk8引入了很多新的特性,比如接口默認值、方法引用、Lambda表達式、函數式接口、Optional、Stream等等,這些在其他語言中并不少見的玩意兒,現今在Java中卻還很少使用,很多時候我們會對新事物(其實已經不新鮮)抱著一種比較保守的態度:反正我司還沒用到,學了也無用武之地;讓別人先去踩踩坑、我來大樹底下好乘涼;又學新東西?我JDK7都沒學完,又TMD要學JDk8、9、10?累覺不愛啊,筆者也一直保持著這種心態,但是一顆好奇的心促使我小小的往前邁了那么一小步……

好奇之心

平常擼代碼的時候經常也會涉及一些多線程的東西,比如使用Future和Callable來搞一些事情,代碼舉例如下:

對于這段代碼在搞什么事情這里就不多說了,值得注意的是IDEA里給“new Callable()”這段代碼“特殊”照顧了一下(注意IDE的language level要設置成JDK8及以上的),想必是要告訴我一些隱晦的事情,本著一顆少男的好奇心我默默的瀏覽了下提示信息,詳細如下圖:

內心的躁動讓我小小點擊了“Replace with lambda”一下?代碼迅速地做了切換:

What an AMAZING thing! 代碼立馬簡潔了許多,整個Callable接口的實現只保留了關鍵的“()->“lambda demo””。這個不止在使用Callable的時候發生,常用的Runnable、Comparator中都會如此,JDK8到底對它們做了什么改變?! 我們不妨舉一個DEMO從最初的夙愿來一步步撥開這一層層面紗~~

循序漸進

DEMO需求:對一個數字型的字符串列表做排序,這個列表很簡單,具體如下:

List<String> list = Arrays.asList("2", "3", "1", "4");

這個需求很簡單,實現起來不需要1分鐘:

Comparator<String> comparator = new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return Integer.valueOf(o1) - Integer.valueOf(o2);} }; list.sort(comparator);

注意本文中所使用的JDK版本為8,所以你看到List的sort()方法的時候不要感到太意外,這是List接口中用默認方法實現的一個新方法:default void sort(Comparator<? super E> c)。對于上面的實現我們還可以很傲嬌的改用一下匿名類的方式:

list.sort(new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return Integer.valueOf(o1) - Integer.valueOf(o2);} });

如果是JDK7,那么用一下Collections.sort()方法,然后差不多實現到這里就結束了,然后JDK8才剛剛開始,我們可以通過進一步的把這個方法改為Lambda表達式的形式實現:

list.sort((String o1, String o2) -> Integer.valueOf(o1) - Integer.valueOf(o2));

好了,一下子就變成一行代碼了,只不過看上去比原先的有那么一丟丟的晦澀。正如上面所說的Callable也好、Runnable也好,和Comparator這種都屬于函數式接口,如果你打開源碼可以發現這三個接口都有一個相同的注解——@FuncationalInterface。如果你所使用的方法中包含有函數式接口,那么你就可以使用Lambda表達式。函數式接口是一種有且只有一個抽象方法的接口,如果標注為@FunctionalInterface的接口沒有抽象方法(空接口也就是標記接口,或者接口中的方法都是默認方法)或者擁有超過一個抽象方法的話都會報錯。
類似于( //會報錯:No target method found.):

@FunctionalInterface public interface FunctionError{}

或者這樣(//會報錯:Multiple non-overriding abstract methods found in interface FunctionError):

@FunctionalInterface public interface FunctionError{public String method1(String o1, String o2);public String method2(Integer o1, Boolean o2); }

都是無效的,可以將上面的其中一個方法改為默認方法:

@FunctionalInterface public interface FunctionCorrect{public String method1(String o1, String o2);default public String method2(Integer o1, Boolean o2){return "why not rabbitmq or kafka?";}; }

這樣就沒有問題。

這里我們先來小結一下——Lambda表達式一個有三個部分:

  • 參數列表。對于上面的Comparable接口而言其參數列表就是“public int compare(String o1, String o2)”中的“(String o1, String o2)”。對于Callable/Runnable來說,其call/run方法沒有參數,所以這里可以表示為一個簡單的括號()。
  • 箭頭符號:->。
  • Lambda表達式主體。也就是“Integer.valueOf(o1) - Integer.valueOf(o2);”。對于本文中第一個示例而言,其Lambda主題即為:““lambda demo.””。Lambda表達式主體的返回值類型 = 函數式接口中方法的返回值類型相同。
    可以看到Lambda的基本語法為:
  • (參數列表)-> 表達式

    或者:

    (參數列表)-> {語句}

    Java還可以推斷出Lambda表達式中的參數類型,上面的代碼還可以進一步優化去掉參數類型的聲明:

    list.sort((o1, o2) -> Integer.valueOf(o1) - Integer.valueOf(o2));

    對于上面的代碼中Integer本身就具有“可比性”(實現了Comparable)接口,上面的代碼可以改寫成:

    list.sort((o1, o2) -> Integer.valueOf(o1).compareTo(Integer.valueOf(o2)));

    不過這樣的代碼易讀性好像也不是很高,我們這里做進一步的改進,這里引入了一個新的概念——方法引用。方法引用讓你可以重復使用現有的方法定義,并像Lambda一樣傳遞他們,在某些情況下,他們更加的易讀。上面的代碼可以進一步的改寫成:

    list.sort(Comparator.comparing(Integer::valueOf));

    這樣的代碼可以看出我們對于String列表的排序規則時其int類型的值,而不用再關注有點晦澀的Lambda語句。如果有一天寶寶不開心了,不按照其轉換的int值排序,而是按照其hashCode排序怎么辦呢,很簡單:

    list.sort(Comparator.comparing(String::hashCode));

    如果寶寶又不開了,原本是升序排序的,現在要按降序排序的怎么辦呢?改寫Lambda表達式,比如這樣:

    list.sort((o1, o2) -> Integer.valueOf(o2).compareTo(Integer.valueOf(o1)));

    不如這樣:

    list.sort(Comparator.comparing(Integer::valueOf).reversed()); //or list.sort(Comparator.comparing(String::hashCode).reversed());

    是不是通俗易懂又方便?方法引用的基本思想是:如果一個Lambda代表的只是直接調用這個方法,那最好還是用名稱來調用它,而不是去描述如何調用它。事實上,方法引用就是讓你根據已有的方法實現來創建Lambda表達式,只不過顯示地指明方法的名稱,代碼可讀性會高一點。當你需要使用方法引用時,將目標引用放在分隔符::前,而方法的名稱放在后面。例如:

    (String s) -> System.out.println(s) 可以等效為 System.out:println

    要不你try一下下面的代碼看看效果是不是一樣的?

    public class FunctionDemo {@FunctionalInterfacepublic interface FunctionQuote{public void print(String arg);}public static void process(FunctionQuote functionQuote){String str = "http://blog.csdn.net/u013256816";functionQuote.print(str);}public static void main(String[] args) {process((String s) -> System.out.println(s));process(System.out::println);} }

    歡迎跳轉到本文的原文鏈接:https://honeypps.com/java/java-lambda-quick-start/


    歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。


    總結

    以上是生活随笔為你收集整理的提升你的代码——Lambda!的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。