Stream操作Collection集合
獨立使用 Stream 的步驟如下:
1 . 使用 Stream 或 XxxStream 的 builder() 類方法創建該 Stream 對應的 Builder。
2 . 重復調用 Builder 的 add() 方法向該流中添加多個元素。
3 . 調用 Builder 的 build() 方法獲取對應的 Stream。
4 . 調用 Stream 的聚集方法。
Stream 提供了大量的聚集方法供用戶調用。對于大部分聚集方法而言,每個 Stream 只能執行一次。例如如下程序。
public class IntStreamTest {public static void main(String[] args) {IntStream is = IntStream.builder().add(20).add(13).add(-2).add(18).build();// 下面調用聚集方法的代碼每次只能執行一行System.out.println("is 所有元素的最大值:" + is.max().getAsInt());System.out.println("is 所有元素的最小值:" + is.min().getAsInt());System.out.println("is 所有元素的總和:" + is.sum());System.out.println("is 所有元素的總數:" + is.count());System.out.println("is 所有元素的平均值:" + is.average());System.out.println("is所有元素的平方是否都大于20: " + is.allMatch(ele -> ele * ele > 20));System.out.println("is是否包含任何元素的平方大于20 : " + is.anyMatch(ele -> ele * ele > 20));// 將is映射成一個新Stream,新Stream的每個元素是原Stream元素的2倍+1IntStream newIs = is.map(ele -> ele * 2 + 1);// 使用方法引用的方式來遍歷集合元素newIs.forEach(System.out::println); // 輸岀 41 27 -3 37} }上面程序先創建了一個 IntStream,接下來分別多次調用 IntStream 的聚集方法執行操作,這樣即可獲取該流的相關信息。
注意:上面 5~13 行代碼每次只能執行一行,因此需要把其他代碼注釋掉。
Stream 提供了大量的方法進行聚集操作,這些方法既可以是“中間的”(intermediate),也可以是 “末端的”(terminal)。
中間方法:中間操作允許流保持打開狀態,并允許直接調用后續方法。上面程序中的 map() 方法就是中間方法。中間方法的返回值是另外一個流。
末端方法:末端方法是對流的最終操作。當對某個 Stream 執行末端方法后,該流將會被“消耗”且不再可用。上面程序中的 sum()、count()、average() 等方法都是末端方法。
除此之外,關于流的方法還有如下兩個特征。
有狀態的方法:這種方法會給流增加一些新的屬性,比如元素的唯一性、元素的最大數量、保證元素以排序的方式被處理等。有狀態的方法往往需要更大的性能開銷。
短路方法:短路方法可以盡早結束對流的操作,不必檢查所有的元素。
Stream 常用的中間方法。
| filter(Predicate predicate) | 過濾 Stream 中所有不符合 predicate 的元素 |
| mapToXxx(ToXxxFunction mapper) | 使用 ToXxxFunction 對流中的元素執行一對一的轉換,該方法返回的新流中包含了 ToXxxFunction 轉換生成的所有元素。 |
| peek(Consumer action) | 依次對每個元素執行一些操作,該方法返回的流與原有流包含相同的元素。該方法主要用于調試。 |
| distinct() | 該方法用于排序流中所有重復的元素(判斷元素重復的標準是使用 equals() 比較返回 true)。這是一個有狀態的方法。 |
| sorted() | 該方法用于保證流中的元素在后續的訪問中處于有序狀態。這是一個有狀態的方法。 |
| limit(long maxSize) | 該方法用于保證對該流的后續訪問中最大允許訪問的元素個數。這是一個有狀態的、短路方法。 |
Stream 常用的末端方法。
| forEach(Consumer action) | 遍歷流中所有元素,對每個元素執行action |
| toArray() | 將流中所有元素轉換為一個數組 |
| reduce() | 該方法有三個重載的版本,都用于通過某種操作來合并流中的元素 |
| min() | 返回流中所有元素的最小值 |
| max() | 返回流中所有元素的最大值 |
| count() | 返回流中所有元素的數量 |
| anyMatch(Predicate predicate) | 判斷流中是否至少包含一個元素符合 Predicate 條件。 |
| allMatch(Predicate predicate) | 判斷流中是否每個元素都符合 Predicate 條件 |
| noneMatch(Predicate predicate) | 判斷流中是否所有元素都不符合 Predicate 條件 |
| findFirst() | 返回流中的第一個元素 |
| findAny() | 返回流中的任意一個元素 |
Collection 接口提供了一個 stream() 默認方法,該方法可返回該集合對應的流,接下來即可通過流式 API 來操作集合元素。由于 Stream 可以對集合元素進行整體的聚集操作,因此 Stream 極大地豐富了集合的功能。
使用 Stream 直接對集合中所有的元素進行批量操作。下面使用 Stream 來改寫這個程序。
public class CollectionStream {public static void main(String[] args) {// 創建一個集合Collection objs = new HashSet();objs.add(new String("中文百度搜索Java教程"));objs.add(new String("中文百度搜索C++教程"));objs.add(new String("中文百度搜索C語言教程"));objs.add(new String("中文百度搜索Python教程"));objs.add(new String("中文百度搜索Go教程"));// 統計集合中出現“中文百度搜索”字符串的數量System.out.println(objs.stream().filter(ele -> ((String) ele).contains("中文百度搜索")).count()); // 輸出 5// 統計集合中出現“Java”字符串的數量System.out.println(objs.stream().filter(ele -> ((String) ele).contains("Java")).count()); // 輸出 1// 統計集合中出現字符串長度大于 12 的數量System.out.println(objs.stream().filter(ele -> ((String) ele).length() > 12).count()); // 輸出 1// 先調用Collection對象的stream ()方法將集合轉換為Stream// 再調用Stream的mapToInt()方法獲取原有的Stream對應的IntStreamobjs.stream().mapToInt(ele -> ((String) ele).length())// 調用forEach()方法遍歷IntStream中每個元素.forEach(System.out::println);// 輸出 11 11 12 10 14} }輸出結果為:
5 1 1 11 11 12 10 14從上面代碼第 11~20 行可以看出,程序只要調用 Collection 的 stream() 方法即可返回該集合對應的 Stream,接下來就可通過 Stream 提供的方法對所有集合元素進行處理,這樣大大地簡化了集合編程的代碼,這也是 Stream 編程帶來的優勢。
上面程序中第 18 行代碼先調用 Collection 對象的 stream() 方法將集合轉換為 Stream 對象,然后調用 Stream 對象的 mapToInt() 方法將其轉換為 IntStream 這個 mapToInt。方法就是一個中間方法,因此程序可繼續調用 IntStream 的 forEach() 方法來遍歷流中的元素。
總結
以上是生活随笔為你收集整理的Stream操作Collection集合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ArrayList和LinkedList
- 下一篇: Jsoup使用选择器语法来查找元素