# Lambda ## 定義 在不同領域,對於Lambda的定義可能不太相同,但概念都是Lambda為一個函數,可以根據輸入的值,決定輸出的值。但Lambda與一般函數不同的是,Lambda並不需要替函數命名(如F(X) = X + 2, G(X) = F(X) + 3中的F、G便是函數的名稱),所以我們常常把Lambda形容為「匿名的」(Anonymous)。 ## Lambda語法結構 input -> body ``` Runnable runnbale = new Runnable() { public void run() { System.out.println("run me!"); } }; ``` 這樣的使用方式,往往會讓Java程式拉的很長,變得十分複雜。因此Lambda最重要的功能,就是取代Functional Interface所產出的匿名類別,簡化程式碼,甚至還可以提升效能(稍候提到)。舉例,同樣的Runnable使用方式,可以減化成: ``` Runnable runnbale = () -> System.out.println("run me!"); ``` 使用Lambda來取代以往Functional Interface的使用方式,<font color="red">可以大大的縮短程式碼,在編譯的過程中,也可以避免掉產生新的.class檔案出來,執行的時候,也不會再重新new出一個物件實體,而是直接將Lambda的body程式碼存放在記憶體</font>,直接以類似call function的方式去執行,大大的提升程式的執行效能。 ## Lambda與Collection的關係 Lambda除了用來取代以往使用Functional Interface的方式外,還可以用在Collection的走訪、過濾和一些簡單的運算上。而且同樣地,使用Lambda可以增加不少的效能。 過去我們使用For each走訪一個List可能要寫成這樣: ``` for (String s : list) { System.out.print(s); } ``` 如果要走訪一個Map更麻煩,可能要寫成這樣: ``` Set<String> keySet = map.keySet(); for (String s : keySet) { System.out.print(s + ":" + map.get(s)); } ``` 若改以Lambda來走訪這些Collection,可以簡化成這樣: ``` list.forEach(s -> System.out.print(s)); ``` ``` map.forEach((k, v) -> System.out.print(k + ":" + v)); ``` 在新的Java 8中,Collection提供了stream()方法,可以對集合做一些過濾和基本運算,而且這個當然也是有經過效能優化過的。除了stream()方法外還有parallelStream()方法,可以讓Collection各別針對它的entry另開出一個Thread,進行stream提供的運算,讓多核心的CPU資源更能有效的被利用。以下將舉幾個過濾和基本運算的例子: ``` List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3"); list.add("5"); list.add("4"); list.stream().filter(s -> Integer.valueOf(s) < 3).forEach(s -> System.out.print(s)); ``` ## Lambda特殊精簡語法結構 什麼!?只要寫方法名稱就好了嗎?甚至連參數也不用傳!是的,Lambda允許這種類型的語法存在,但必須要明確指定方法名稱是在哪個類別或是哪個物件之下,而且最後一個「.」要改成「::」。這樣說好像很模糊,舉幾個例子好了: ``` interface B { public void doStringWork(String s); } interface C { public double doComputeWork(float x, float y); } public class A { public A() { B b = this::printOnce; b.doStringWork("哈囉"); } public static void main(String[] args) { B b = A::printTwice; b.doStringWork("嗨"); new A(); C c = Math::pow; b.doStringWork(String.valueOf(c.doComputeWork(2.5f, 2))); } public static void printTwice(String s) { System.out.print(s); System.out.println(s); } public void printOnce(String s) { System.out.println(s); } } ``` ###### tags: `java` `Lambda`