深入理解Java Stream

Java 8引入的Stream API是一個功能強大、靈活且可組合的流處理模式,它允許我們以一種比傳統的for循環更簡潔、更易於閱讀和管理的方式處理數據。Stream API基於Lambda表達式和方法引用實現了一種函數式編程樣式,可以將我們的程序從特定的實現中解耦出來。本篇文章將介紹Java Stream的用法和特性,旨在幫助讀者更好地掌握和運用Java Stream。

一、生成Stream

Stream可以從數組、集合、文件、網絡、任何對象等多種數據源生成,我們可以使用Stream的靜態方法創建Stream、或者將已有的Stream處理成新的Stream,這些靜態方法包括:

Stream.of(T...)
Stream.empty()
Arrays.stream(T[])
Collection.stream()

其中,Stream.of()用於將數組或任意個數的元素轉換為Stream;Stream.empty()用於生成空的Stream;Arrays.stream()用於將數組轉換為Stream;Collection.stream()用於將Collection轉換為Stream。

二、Stream的操作

1. 中間操作

中間操作是指返回Stream類型的操作,可以被其他Stream操作鏈式調用,例如filter()、map()、sorted()、distinct()等。這些操作可以串接使用,我們可以在一個Stream上執行多個中間操作,以構建出一個複雜邏輯的數據流處理鏈。

1.1 filter()

filter()方法用於排除不符合條件的元素,該方法需要傳入一個Predicate類型的Lambda表達式,該表達式接受一個參數,並返回一個boolean類型的結果,如果結果為true,則保留該元素;如果為false,則排除該元素。例如,篩選出一個整數集合中所有大於等於5的元素:

IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    .filter(num -> num >= 5)
    .forEach(System.out::println);

該代碼會輸出:

5
6
7
8
9
10
1.2 map()

map()方法用於將一個元素轉換為另一個類型的元素,它需要傳入一個Function類型的Lambda表達式,該表達式接受一個參數,並返回一個處理後的結果。例如,將一個字符串集合中所有的字符串轉換為大寫格式:

List list = Arrays.asList("apple", "banana", "orange");
list.stream()
    .map(String::toUpperCase)
    .forEach(System.out::println);

該代碼會輸出:

APPLE
BANANA
ORANGE
1.3 flatMap()

flatMap()方法可以將一個Stream中的每個對象分解為多個Stream,最後將多個Stream合成一個Stream並返回。flatMap()方法需要傳入一個Function類型的Lambda表達式,該表達式接受一個參數,並返回一個Stream類型的結果。例如,取出一個集合中所有字符串的單詞,並將其輸出:

List list = Arrays.asList("Hello World", "Stream API");
list.stream()
    .flatMap(str -> Stream.of(str.split(" ")))
    .forEach(System.out::println);

該代碼會輸出:

Hello
World
Stream
API
1.4 distinct()

distinct()方法用於去重,它返回一個去除了重複元素的新Stream。如果集合元素沒有重寫equals()和hashCode()方法,則該方法只能使用在基本類型Stream上。例如,去除一組數字中的重複元素:

IntStream.of(1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8)
    .distinct()
    .forEach(System.out::println);

該代碼會輸出:

1
2
3
4
5
6
7
8
1.5 sorted()

sorted()方法用於對Stream中的元素進行排序,排序時可以自定義排序規則,排序最終會返回一個新的Stream。例如,對一組數字進行排序:

IntStream.of(4, 2, 5, 1, 6, 3)
    .sorted()
    .forEach(System.out::println);

該代碼會輸出:

1
2
3
4
5
6

2. 終止操作

終止操作是指返回非Stream類型的操作,它們將Stream管道處理後的結果輸出或返回。在一個Stream管道中,只有一個終止操作才會觸發流動處理,終止操作是Stream管道處理的必要環節。終止操作包括:

  • forEach()
  • count()
  • findFirst()
  • reduce()
  • toArray()
  • collect()
2.1 forEach()

forEach()方法用於遍歷Stream中的元素,它會接收一個Consumer類型的Lambda表達式作為參數,該表達式接受一個參數,並沒有返回值。例如,遍歷一個整數集合併輸出其平方:

IntStream.of(1, 2, 3, 4, 5)
    .forEach(num -> System.out.println(num * num));

該代碼會輸出:

1
4
9
16
25
2.2 count()

count()方法用於計算Stream中元素的個數,返回一個long類型的結果。例如,計算一組數字的個數:

long count = IntStream.of(1, 2, 3, 4, 5).count();
System.out.println("count: " + count);

該代碼將輸出:

count: 5
2.3 findFirst()

findFirst()方法用於查找Stream中第一個符合條件的元素,返回一個Optional類型的結果。例如,查找一組字符串中第一個以大寫字母開頭的元素:

List list = Arrays.asList("a", "b", "C", "d");
Optional firstUpper = list.stream().filter(str -> Character.isUpperCase(str.charAt(0))).findFirst();
System.out.println("first upper: " + firstUpper.orElse("not found"));

該代碼將輸出:

first upper: C
2.4 reduce()

reduce()方法用於對Stream中的所有元素進行“累加”處理,並返回處理結果。reduce()方法需要傳入兩個參數,第一個參數是初始值,第二個參數是一個BinaryOperator類型的Lambda表達式,該表達式接收兩個同類型的參數,並返回一個同類型的結果。例如,計算一組數字的和:

int sum = IntStream.of(1, 2, 3, 4, 5).reduce(0, (a, b) -> a + b);
System.out.println("sum: " + sum);

該代碼將輸出:

sum: 15
2.5 toArray()

toArray()方法用於將Stream生成一個數組,返回一個T[]類型的結果。例如,將集合中所有的元素保存到數組中:

List list = Arrays.asList("a", "b", "c");
String[] arr = list.stream().toArray(String[]::new);
System.out.println("array: " + Arrays.toString(arr));

該代碼將輸出:

array: [a, b, c]
2.6 collect()

collect()方法是非常重要的一個操作,它可以將Stream中的所有元素按照指定的方式收集起來,可以選取任何類型的集合、Map、數組,或者自定義的Collector進行收集操作。例如,將一組字符串拼接為一個字符串:

List list = Arrays.asList("a", "b", "c");
String str = list.stream().collect(Collectors.joining("-"));
System.out.println("merged string: " + str);

該代碼將輸出:

merged string: a-b-c

三、並行處理與性能

Stream API支持並行處理,可以讓程序利用多核CPU的優勢,提高數據處理性能。我們可以通過parallel()方法將一個Stream切換為並行流,或者通過sequential()方法將並行流切換為順序流。例如,計算一組整數的平方和:

long start = System.currentTimeMillis();
int result = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
                      .parallel() // 切換為並行流
                      .map(num -> num * num)
                      .reduce(0, (a, b) -> a + b);
long end = System.currentTimeMillis();
System.out.println("result: " + result);
System.out.println("time used: " + (end - start) + "ms");

該代碼將輸出:

result: 385
time used: 11ms

當然,並不是所有情況都適合使用並行流,可能會存在以下問題:

  • 數據量較小:並行流的創建和銷毀需要一定的時間,當數據量很小時,順序流可能會更快。
  • 有些操作不適合併行處理:例如排序和去重。
  • 有些操作需要先完成一部分才能進行下一步操作:例如findFirst()。

四、結束語

Java Stream API是Java 8引入的重要特性之一,雖然Stream看起來很複雜,但實際上它是與函數式編程思想一脈相承的,它可以幫助我們更好地編寫與數據處理相關的代碼。本文介紹了Stream的基本用法、操作類型和並行處理特性,希望能夠幫助讀者更好地掌握和運用Java Stream API。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/303781.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-31 11:50
下一篇 2024-12-31 11:50

相關推薦

  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29
  • Java 8 Group By 會影響排序嗎?

    是的,Java 8中的Group By會對排序產生影響。本文將從多個方面探討Group By對排序的影響。 一、Group By的概述 Group By是SQL中的一種常見操作,它…

    編程 2025-04-29

發表回復

登錄後才能評論