Lambdas:来到您附近的Java 8!
什么是Lambda?
Lambda表達式是一種匿名函數,可以在方法中內聯編寫,并且可以在使用表達式的任何地方使用。 有時您可能會發現它們被稱為閉包,盡管我在下面解釋了對該參考的一些注意事項。 像普通的Java方法一樣,它具有參數和可以執行的主體。 lambda表達式是Java 8中令人興奮的新功能之一,它已定義為JSR 335的一部分。
添加lambda表達式將使Java更輕松地支持函數式編程技術和高階函數。 這并不是說突然變成一夜之間成為一種異乎尋常而深奧的語言(例如Haskell),但是它將朝著與C#,Ruby或python之類的語言相同的方向發展。 也就是說,為有意義的功能樣式提供部分支持,但仍然允許您使用命令式技術,例如可變變量。
基本語法
這是一個lambda表達式,它使數字增加1:
x -> x + 1如您所見,表達式以參數開頭,以參數主體結尾,并用箭頭將兩者分開。 您也可以顯式鍵入參數,在類型注釋上放置類型注釋或具有多個參數。 如果您想執行這些操作,則需要將參數放在方括號中,例如:
// Explicit Types(Integer x) -> x + 1// Multiple Arguments(Integer x1, Integer x2) -> x1 + 1// Annotations:(Integer x1, @SuppressWarnings("unused") Integer x2) -> x1 + 1到目前為止,所有的lambda主體都是表達式,但是您也可以像常規方法一樣,將主體編寫為一系列語句。
(x) -> { x += 5; System.out.println(x); return x; };由于lambda是正則表達式,因此您可以將其視為正則表達式。 例如,您可以將它們分配給變量,將它們作為參數傳遞給其他方法。
// a method: public static void useFunc(IntFun f) { System.out.println(f.apply(2)); } // in code IntFun inc = x -> x + 1; useFunc(inc); useFunc(x -> x + 1);類型?
由于這是Java,因此即使不是所有這些“ x”參數都標記為“整數”,所有這些函數仍然是靜態類型的。 幸運的是,Java 7中方法句柄的引入提供了一種引用方法本身的方法。 這意味著您的函數并不需要全部實現某個通用接口,它們可以是被認為是“函數接口”的任何東西。
引用規范草案,“功能接口是僅具有一種抽象方法的接口,因此表示單個功能協定。” 這些也可以用首字母縮寫詞“ SAM”來表示,它代表“單一抽象方法”。 例如:
interface Runnable { void run(); } interface Function { public R apply(A a); } interface IntFun extends Function {} // equals is defined by java.lang.Object, so this only has one abstract method interface Comparator { boolean equals(Object obj); int compare(T o1, T o2); }因此,通過確保使用保持這些約束的接口,當前正在編寫/正在編寫的任何API都可以被lambda使用。 Guava庫是一個已經鼓勵有限的函數編程風格的示例API。
更有趣的例子
經驗豐富的函數式程序員會意識到map函數,該函數會為您返回一個新列表,其中每個值都由函數更改。 在番石榴世界中,此功能稱為“變換”。 這是您今天可以編寫的一些Java代碼示例,使用它來遞增列表:
Collection result = transform(newArrayList(1, 2, 3), new Function() { @Override public Integer apply(Integer x) { return x + 1; } });這是一個高階函數的示例,即以函數為參數或返回函數的函數。 轉換功能使迭代集合的過程抽象化,并建立一個新的集合,從而可以編寫更多抽象的高級代碼。 不幸的是,由于強制使用了許多行噪聲,因此在一定程度上克服了可讀性的優勢,但是如果您使用lambda重寫它:
Collection result = transform(newArrayList(1, 2, 3),x -> x + 1);另一個常用的高階函數是濾波函數。 如果為它提供一個集合和一個謂詞,它將返回一個新集合,其中包含謂詞對其適用的舊集合中的元素。 這是一個用匿名內部類樣式和lambda表達式方式編寫的代碼示例。
Collection threeAndFive = filter(newArrayList(1, 3, 5), new Predicate() { @Override public boolean apply(Integer x) { return x > 2; } }); Collection threeAndFiveByLambda = filter(newArrayList(1, 3, 5),x -> x > 2);方法參考
當然,您可能已有一個已經定義了許多方法的現有代碼庫,您希望使用它們代替lambda。 目前,這在Java中使用匿名內部類也是可能的,但同樣麻煩。 除了提供lambda表達式外,JSR 335還提出了一些語法糖,以使此過程更容易。 您可以使用'::'符號作為已編寫的現有方法的方法參考。 這是前面的示例,但是使用了方法參考:
// Existing method public static boolean greaterThanTwo(Integer x) { return x > 2; } // prints [3, 5] System.out.println(filter(newArrayList(1,3,5),LambdasExample::greaterThanTwo));他們真的是閉包嗎?
在引言中,我提到過lambda表達式可以稱為closures 。 這意味著一個函數能夠引用其正常范圍之外的變量,或者被封閉在周圍范圍的自由變量之上。
int value = 5; IntFun addValue = x -> x + value;在此代碼示例中,“ addValue”函數能夠在周圍的范圍內引用名為“ value”的變量,盡管對此有一些警告。 如果您之前編寫過匿名內部類,那么您會記得它們只能引用標記為final的周圍變量,即未分配給它們。 這里的限制是相似的,只是它已被概括為最終有效的限制 。 簡而言之,您可以引用未分配給多個變量的變量。 原理是,如果將變量標記為final或可以將其標記為final而不引入編譯器錯誤,則該變量實際上是final。
嘗試和鏈接
lambdas規范的早期草案審核的一部分已經在線發布,并且如果您想了解正在發生的事情的來龍去脈,那么這可能對您來說很有趣。 如果您有興趣嘗試編寫一些lambda代碼,則已經有二進制快照 。 這些內容經常更新,如果您想了解lambda內部結構的實質,可以嘗試構建源代碼 。 關于使用二進制代碼編寫代碼的唯一警告是,由于它仍處于草稿版本中,并且仍使用“#”運算符代替“ ::”作為方法參考語法,因此它仍然存在一些bug。
摘要
 這是對Java 8 Lambda表達式的一些概念的介紹,因此簡化了所涉及的一些問題,但是對于讀者來說,了解即將發生的事情應該足夠了。 很高興看到Oracle在事物的語言方面引入了一些有用的更改,這種更改已經停滯了一段時間。 
翻譯自: https://www.javacodegeeks.com/2013/07/lambdas-coming-to-a-java-8-near-you.html
總結
以上是生活随笔為你收集整理的Lambdas:来到您附近的Java 8!的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 安卓是谷歌的吗(安卓是谷歌的)
- 下一篇: linux rm命令详解(linux r
