博客 / 詳情

返回

Java8新特性Stream

Stream 是 Java 8 引入的一種新的抽象,用於處理集合類 (Collection) 的數據。Stream 並不存儲數據,而是按需計算數據。Stream 操作有兩個重要特性:

  1. 流水線操作 (Pipelining):Stream 操作可以鏈式調用,形成一個流水線,這些操作既可以是中間操作(intermediate operation),也可以是終端操作(terminal operation)。
  2. 內部迭代 (Internal Iteration):不同於集合類的外部迭代 (external iteration),Stream 使用內部迭代,通過底層的迭代器實現。

Stream 的優點

  1. 簡潔性:Stream API 提供了聲明性的方法鏈來處理數據,這使得代碼更簡潔、更易讀。
  2. 易於並行化:Stream API 提供了簡單的並行化處理數據的方式,通過 parallelStream 可以輕鬆實現並行計算,提高處理性能。
  3. 函數式編程風格:Stream API 支持函數式編程,允許使用 Lambda 表達式和方法引用,減少了樣板代碼。
  4. 延遲執行:中間操作是惰性求值的,只有在終端操作執行時才會計算,優化了性能。
  5. 更高的抽象層次:Stream API 提供了一種更高層次的數據處理抽象,使得代碼更具表達力和可維護性。

    用途

    Stream API 主要用於對集合數據進行操作,比如過濾、排序、映射、歸約等。它提供了一種函數式編程的風格,使代碼更簡潔、易讀、可維護。常見用途包括:

  • 過濾 (Filtering):從集合中篩選出符合條件的元素。
  • 映射 (Mapping):將集合中的每個元素映射成另一種形式。
  • 歸約 (Reduction):將集合中的元素組合成一個值。
  • 收集 (Collecting):將處理後的數據轉換為其他集合形式。
  • 統計 (Statistics):對數據進行統計計算,如計數、求和、平均值等。

常用的 Stream 操作示例:

1. 創建 Stream

List<String> list = Arrays.asList("a", "b", "c", "d");

// 從集合創建 Stream
Stream<String> stream = list.stream();

// 從數組創建 Stream
Stream<String> stream = Stream.of("a", "b", "c", "d");

2. 中間操作 (Intermediate Operations)

中間操作會返回一個新的 Stream,它們是惰性求值的,只有在終端操作執行時才會執行。

// 過濾
Stream<String> filteredStream = stream.filter(s -> s.startsWith("a"));

// 映射
Stream<String> mappedStream = stream.map(String::toUpperCase);

// 排序
Stream<String> sortedStream = stream.sorted();

// 去重
Stream<String> distinctStream = stream.distinct();

 // 排序
Stream<String> sortedStream = stream.sorted();
Stream<String> sortedByComparator = stream.sorted((s1, s2) -> s2.compareTo(s1));

3. 終端操作 (Terminal Operations)

終端操作會觸發 Stream 的計算,並生成一個結果或副作用。

// 收集
List<String> collectedList = stream.collect(Collectors.toList());

// 統計
long count = stream.count();

// 查找
Optional<String> firstElement = stream.findFirst();

//reduce:歸約操作,將元素組合成一個值
Optional<String> concatenated = stream.reduce((s1, s2) -> s1 + s2);

代碼案例

案例 1:過濾和映射

List<String> strings = Arrays.asList("apple", "banana", "orange", "apple", "mango");

List<String> result = strings.stream()        //獲取stream對象
        .filter(s -> s.startsWith("a"))       //過濾,檢查列表中是否以“a”開頭,滿足條件保留到流中
        .map(String::toUpperCase)             //映射,將流中每個字符串轉換為大寫
        .collect(Collectors.toList());        //收集,將流中的元素收集到一個list中

System.out.println(result);  // 輸出:[APPLE, APPLE]

案例 2:排序和去重

 List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);

List<Integer> result = numbers.stream()
        .distinct()                            //去重
        .sorted()                              //排序
        .collect(Collectors.toList());

System.out.println(result);  // 輸出:[2, 3, 5, 7]

案例 3:歸約操作

 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

int sum = numbers.stream()
        .reduce(0, Integer::sum);   //reduce:歸約操作,將元素組合成一個值

System.out.println(sum);  // 輸出:15

案例 4:分組操作

List<String> strings = Arrays.asList("apple", "banana", "orange", "apple", "mango");

Map<String, Long> result = strings.stream()
        .collect(Collectors.groupingBy(s -> s, Collectors.counting()));

    //終端操作,收集 使用Collectors.groupingBy()方法來收集流中的元素。
    // 這個方法接受兩個參數:一個是分類函數(在這裏是s -> s,表示使用字符串本身作為鍵)
    // 另一個是下游的收集器(在這裏是Collectors.counting(),用於計算每個鍵的出現次數)。

System.out.println(result);  // 輸出:{orange=1, banana=1, apple=2, mango=1}

案例 5:並行流

List<String> strings = Arrays.asList("apple", "banana", "orange", "apple", "mango");

List<String> result = strings.parallelStream()   //並行處理集合中的數據,適用與大規模的計算、數據轉換、過濾等操作
        .filter(s -> s.startsWith("a"))
        .map(String::toUpperCase)
        .sorted()
        .collect(Collectors.toList());

System.out.println(result);  // 輸出:[APPLE, APPLE]

案例 6:生成數列

List<Integer> numbers = IntStream.range(1, 10)   //創建了一個從1到9的整數序列的IntStream
        .boxed()    //將IntStream中的原始類型int轉換成Integer對象的Stream
        .collect(Collectors.toList());

System.out.println(numbers);  // 輸出:[1, 2, 3, 4, 5, 6, 7, 8, 9]

案例 7:字符串拼接

List<String> strings = Arrays.asList("apple", "banana", "orange");

String result = strings.stream()
        .collect(Collectors.joining(", "));   //字符串拼接

System.out.println(result);  // 輸出:apple, banana, orange

注意事項

1.排序 stream.sorted()

Stream<String> sortedStream = stream.sorted();
Stream<String> sortedByComparator = stream.sorted((s1, s2) -> s2.compareTo(s1));
  1. 無參的 sorted():元素按照它們的自然順序排序。如果你的元素是數字或字符串等基本類型,它們將按照自然數值或字典順序排序。如果你的元素是對象,它們將按照 Comparable 接口中定義的順序排序。
  2. 帶Comparator的 sorted():元素按照你提供的 Comparator 排序。這允許你定製排序邏輯,例如,你可以按字符串長度排序、按某個屬性的逆序排序等。

2.中間操作 (Intermediate Operations) 和 終端操作 (Terminal Operations) 的區別

  • 中間操作:

    • 返回一個新的 Stream。
    • 惰性求值:中間操作本身不會觸發實際的計算,只有在終端操作執行時才會計算。
    • 例子:filter, map, flatMap, distinct, sorted, limit, skip, peek。
  • 終端操作:

    • 觸發 Stream 的計算,並生成結果。
    • 不是惰性求值,一旦調用終端操作,整個 Stream 的計算就會執行。
    • 終端操作會關閉 Stream,之後不能再對其進行操作。
    • 例子:forEach, toArray, reduce, collect, min, max, count, anyMatch, allMatch, noneMatch, findFirst, findAny。

轉載自開思通智網:https://www.opensnn.com/os/article/10000908

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.