Java 8 Lambda 表達式及 Stream 在集合中的用法


簡介

雖然 Java 8 已經發布有一段時間了,但是關於 Java 8 中的 Lambda 表達式最近才開始系統的學習,剛開始就被 Stream 的各種騷操作深深的吸引住了,簡直漂亮的不像 Java。我認為每一個用 Java 的都應該深入的學習一下,不僅可以寫出漂亮的代碼,更可以對代碼進行更深層次的抽象。

Stream

Java 8 中新新增了 Stream(流) 類來簡化集合類的使用,Stream 本質上是個接口,接口中定義了很多對 Stream 對象的操作;那 Stream 又是什么呢?我們知道, Java 中所有的集合都是基於 Collection 接口的擴展,在 Java 8 中新增了 stream() 方法來獲取 Stream 對象,方法如下:

default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}

注意:default 也是 Java 8 中新引入的關鍵字,用於定義接口中方法的默認實現 。
所以 Java 中所有的集合都包含這個方法,我們可以通過 stream() 方法獲取這個集合的 Stream 對象。


先來看一個簡單的使用案例以便更深入的理解:
對一個 List 求和一般的代碼需要這么寫:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = 0;
for (int i = 0; i < list.size(); i++) {
sum += list.get(i);
}
System.out.println(sum);

這樣的樣板代碼我們可能每天都要寫個好多遍,非常繁瑣,而且容易出錯,可讀性差,下面改成 Stream 方式:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = list.stream().reduce(0, (acc, value) -> acc + value);
System.out.println(sum);

改成這樣一目了然,代碼非常干凈利索,上面代碼先通過 stream() 方法獲取 Stream 對象,然后調用 Stream 中的 reduce 方法計算,然后獲取結果(這里先不用考慮 reduce 是什么,后面會詳細介紹);
上面便是 Stream 的一次簡單操作。下面來具體說一下。
Stream 中主要包含如下幾個方法:

方法名 簡介
collect(toList()) 通過 Stream 生成一個列表
map 將流中的一個值轉換成一個新的值
filter 過濾 Stream 中的元素
flatMap 將多個 Stream 連接成一個 Stream
max 求最大值
min 求最小值
reduce 從一組值中生成一個新的值
上面就是 Stream 中包含的幾個主要方法,下面逐一對其介紹:

collect(toList()) & filter

collect(toList()) 的作用是通過一個 Stream 對象生成 List 對象,案例:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = list.stream().filter((value) -> value > 2).collect(toList());
result.forEach((value) -> System.out.print(value));

 

 

上面的代碼先創建了一個 List 對象並初始化,然后篩選出大於 2 的值,輸出。
filter 方法的作用是過濾 Stream 中的元素,filter 方法是一個高階函數,接收一個函數接口作為參數,此高階函數返回一個 boolean 值,返回 true 的元素會保留下來;
collect(toList()) 方法將 filter 操作返回的 Stream 生成一個 List。

高階函數:接收或返回一個函數接口的函數稱為高階函數。
函數接口:只包含一個函數的接口成為函數接口。
map

map 函數的作用是將流中的一個值轉換成一個新的值,舉個例子,我們要將一個 List 轉換成 List ,那么就可以使用 map 方法,示例代碼:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<String> result = list.stream().map(value -> String.format("String:%s", value)).collect(toList());
result.forEach(System.out::print);
1
2
3
map 方法將 Integer 元素轉換成 String 並使用 collect(toList()) 方法生成一個新的 List。

System.out::print 是 (value) -> System.out.print(value) 的簡化版寫法。
flatMap

flatMap:將多個 Stream 連接成一個 Stream,這個怎么理解呢,舉個栗子:
首先定義一個 List 對象,將這個對象中的每一個 String 都分割成一個字母並生成一個新的 List 對象,代碼:

List<String> list = Arrays.asList("abc", "def", "ghi");
List<Character> result = list.stream().flatMap(value -> {
char[] chars = value.toCharArray();
Character[] characters = new Character[chars.length];
for(int i = 0; i < characters.length; i++){
characters[i] = chars[i];
}
return Stream.of(characters);
}).collect(toList());
result.forEach(System.out::println);

上面代碼先遍歷 list ,通過 flatMap 函數將每個 String 元素都生成一個新的 Stream 並將這些 Stream 連接成一個新的 Stream。

max&min

求最大值最小值,這個很好理解了,直接看代碼:

List<Integer> list = Arrays.asList(0, 1, 2, 3);
Comparator<Integer> comparator = (o1, o2) -> o1.compareTo(o2);
System.out.println(list.stream().min(comparator).get());
System.out.println(list.stream().max(comparator).get());

min 和 max 函數需要一個 Comparator 對象為參數作為比對依據。

reduce

從一組值中生成一個新的值,reduce 函數其實用途非常廣泛,作用也比較大,我們舉一個累加的例子:

List<Integer> list = Arrays.asList(0, 1, 2, 3);
int count = list.stream().reduce(0, (acc, item) -> acc + item).intValue();
System.out.println(count);

reduce 函數的一個參數為循環的初始值,這里計算累加時初始值為 0,acc 代表已經計算的結果,item 表示循環的每個元素。

到此 Stream 中的幾個常用方法就介紹完了,其他方法可以自己 Stream 代碼。


原文:https://blog.csdn.net/u013872857/article/details/79439444


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM