須要Lambda表達式的緣由主要有三個:java
1. 更緊湊的代碼編程
2. 經過提供額外的功能對方法的功能進行修改的能力數據結構
3. 更好地支持多核處理多線程
更緊湊的代碼併發
Lambda表達式以一種簡潔的方式去實現僅有一個方法的Java類。框架
例如,若是代碼中有大量的匿名內部類–諸如用於UI應用中的監聽器與處理器實現,以及用於併發應用中的Callable與Runnable實現–在使用了Lambda表達式以後,將使代碼變得很是短,且更易於理解。函數式編程
修改方法的能力函數
有時,方法不具有咱們想要的一些功能。例如,Collection接口中的contains()方法只有當傳入的對象確實存在於該集合對象中時纔會返回true。但咱們沒法去幹預該方法的功能,好比,若使用不一樣的大小寫方案也能夠認爲正在查找的字符串存在於這個集合對象中,咱們但願此時contains()方法也能返回true。優化
簡單點兒說,咱們所指望作的就是」將咱們本身的新代碼傳入」已有的方法中,而後再調用這個傳進去的代碼。Lambda表達式提供了一種很好的途徑來表明這種被傳入已有方法且應該還會被回調的代碼。編碼
更好地支持多核處理
當今的CPU具有多個內核。這就意味着,多線程程序可以真正地被並行執行,這徹底不一樣於在單核CPU中使用時間共享這種方式。經過在Java中支持函數式編程語法,Lambda表達式能幫助你編寫簡單的代碼去高效地應用這些CPU內核。
例如,你可以並行地操控大集合對象,經過利用並行編程模式,如過濾、映射和化簡(後面將會很快接觸到這些模式),就可以使用到CPU中全部可用的硬件線程。
一. 基本概念
1.1 爲何加入 集合的流式操做
JDK8 的Stream 是一個受到 函數式編程 和 多核時代影響而產生的東西。不少時候咱們須要到底層返回數據,上層再對數據進行遍歷,進行一些數據統計,可是以前的Java API 中不多有這種方法,這就須要咱們本身來 Iterator 來遍歷,若是JDK 可以爲咱們提供一些這種方法,而且可以爲咱們優化就行了。
因此JDK8加入 了 java.util.stream包,實現了集合的流式操做,流式操做包括集合的過濾,排序,映射等功能。根據流的操做性,又能夠分爲 串行流 和 並行流。根據操做返回的結果不一樣,流式操做又分爲中間操做和最終操做。大大方便了咱們對於集合的操做。
最終操做:返回一特定類型的結果。
中間操做:返回流自己。
1.2 什麼是 流
Stream 不是 集合元素,也不是數據結構,它至關於一個 高級版本的 Iterator,不能夠重複遍歷裏面的數據,像水同樣,流過了就一去不復返。它和普通的 Iterator 不一樣的是,它能夠並行遍歷,普通的 Iterator 只能是串行,在一個線程中執行。
二. 串行流和並行流:
串行流操做在一個線程中依次完成。並行流在多個線程中完成,主要利用了 JDK7 的 Fork/Join 框架來拆分任務和加速處理。相比串行流,並行流能夠很大程度提升程序的效率。
三. 中間操做 和 最終操做
中間操做:
filter(): 對元素進行過濾
sorted():對元素排序
map():元素映射
distinct():去除重複的元素
最終操做:
forEach():遍歷每一個元素。
reduce():把Stream 元素組合起來。例如,字符串拼接,數值的 sum,min,max ,average 都是特殊的 reduce。
collect():返回一個新的集合。
min():找到最小值。
max():找到最大值。
3.1 filter() 對元素進行過濾
Demo(有一鏈表,{1,2,3,4,5},把偶數過濾掉):
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); for(int i = 1 ; i <= 5; ++i){ list.add(i); } list.stream().filter(param -> (int)param % 2 == 1) .forEach(System.out::println); } }
輸出:
1 3 5
3.2 sorted() 對元素進行排序
Demo(有一鏈表,{2,3,1,5,4},從小到大排序):
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(2); list.add(3); list.add(1); list.add(5); list.add(4); list.stream().sorted().forEach(System.out::println); } }
輸出:
1 2 3 4 5
Ps1: 此時爲升序,那麼有時候咱們可能會須要到降序,此時作法能夠以下:
流除了提供默認的升序 sorted() 方法,也提供了:
Stream<T> sorted(Comparator<? super T> comparator);
那麼,自定義比較函數便可,以下代碼:
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(2); list.add(3); list.add(1); list.add(5); list.add(4); // list.stream().sorted().forEach(System.out::println); list.stream().sorted( (param1,param2) -> ((int)param1 < (int)param2 ? 1 : -1 ) ) .forEach(System.out::println); } }
輸出爲:
5 4 3 2 1
3.3 map() 元素映射
也就是說,原來的鏈表的每一個元素能夠按照規則變成相應的元素。
Demo(鏈表 (1,0),變成 true,false):
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(1); list.add(0); list.stream().map( param -> (int)param == 1 ? true:false ) .forEach(System.out::println); } }
輸出:
true false
3.4 distinct() 去除重複元素
Demo:
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(1); list.add(1); list.add(0); list.stream().distinct().forEach(System.out::println); } }
3.5 reduce() :把Stream 元素組合起來。
Demo(從1加到5):
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); System.out.println( list.stream().reduce((param1,param2) ->(int)param1 + (int)param2 ).get()); } }
注意,reduce() 返回一個 Optional 類型的對象,能夠經過 get() 方法得到值。
3.6 collect() :返回一個新的集合
Demo(先把 list 集合的 奇數去掉,而後把剩下的偶數返回到 _list 集合中):
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); List _list = (List) list.stream().filter((param) -> (int)param % 2 == 0) .collect(Collectors.toList()); _list.forEach(System.out::println); } }
輸出:
2 4
3.7 min(),max() 找到最大值最小值
public class Test { public static void main(String[] args) throws InterruptedException { List list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); System.out.println(list.stream().min( (param1,param2) -> (int)param1 > (int)param2 ? 1:-1 ).get()); System.out.println(list.stream().max( (param1,param2) -> (int)param1 > (int)param2 ? 1:-1 ).get()); } }
注意, min(),max() 方法也是返回 Optional 對象, 能夠經過 get() 方法返回值。 總結: 1. 流式操做的引入:提升執行效率(並行),方便編碼(有不少API 可用),提升可讀性。 2. 流的分類:能夠分爲串行流和並行流;對於操做:能夠分爲中間操做和最終操做 3. 流API: 中間操做: filter(): 對元素進行過濾; sorted():對元素排序; map():元素映射; distinct():去除重複的元素 。 最終操做: forEach():遍歷每一個元素; reduce():把Stream 元素組合起來。例如,字符串拼接,數值的 sum,min,max ,average 都是特殊的 reduce。 collect():返回一個新的集合。 min():找到最小值。 max():找到最大值。