在 Java 中,Stream(流) 是 Java 8 引入的核心特性,本質是 對數據源(集合、數組等)進行高效操作的 “元素序列” —— 它不存儲數據,也不修改原數據源,而是通過一系列 “中間操作”(如過濾、排序、映射)和 “終端操作”(如收集、遍歷、統計),以聲明式(而非命令式)的方式處理數據,讓代碼更簡潔、高效、易讀。

一、先搞懂:Stream 不是什麼? 不是集合 / 數組:不存儲元素,僅 “流經” 元素(類似水流,只傳遞數據,不保存); 不修改原數據源:所有操作都返回新的 Stream 或最終結果,原始數據不變; 不是迭代器:但支持類似迭代的 “遍歷”,且支持並行處理(無需手動寫多線程); 一次性使用:Stream 被終端操作消費後,就不能再重複使用(需重新創建)。 二、Stream 的核心特性

  1. 聲明式編程(關注 “做什麼”,而非 “怎麼做”) 命令式編程(Java 8 前):需手動寫循環、判斷邏輯(如篩選偶數);聲明式編程(Stream):直接描述 “篩選偶數” 的目標,底層實現由 Stream 框架完成。

示例對比:

// 命令式(手動循環篩選) List evens = new ArrayList<>(); for (int num : numbers) { if (num % 2 == 0) { evens.add(num); } }

// 聲明式(Stream 篩選) List evens = numbers.stream() .filter(num -> num % 2 == 0) .collect(Collectors.toList()); AI構建項目

  1. 中間操作 + 終端操作(惰性執行) 中間操作:返回新的 Stream,不立即執行(如 filter、sorted、map、limit);多箇中間操作可 “鏈式調用”,形成操作管道(Pipeline); 終端操作:觸發實際計算,消費 Stream,返回非 Stream 結果(如 forEach、collect、count、average);只有調用終端操作,中間操作才會一起執行(惰性執行,提升效率)。 示例:

numbers.stream() .filter(num -> num % 2 == 0) // 中間操作(不執行) .sorted() // 中間操作(不執行) .forEach(System.out::println); // 終端操作(觸發所有中間操作執行) AI構建項目 3. 支持並行處理(簡單高效) Stream 分為 “串行流” 和 “並行流”:

串行流:單線程處理(默認,stream() 生成); 並行流:多線程處理(parallelStream() 生成或 parallel() 轉換),無需手動管理線程。 示例(並行篩選偶數,自動多線程):

List evens = numbers.parallelStream() .filter(num -> num % 2 == 0) .collect(Collectors.toList()); AI構建項目 4. 無狀態 + 有狀態操作 無狀態:每個元素的處理不依賴其他元素(如 filter、map),效率高; 有狀態:處理元素需依賴其他元素(如 sorted 需收集所有元素才能排序,limit 需計數),可能需要緩存。 三、Stream 的核心結構(3 步流程) 使用 Stream 通常分為 3 步:創建 Stream → 中間操作(鏈式)→ 終端操作(觸發執行)

  1. 第一步:創建 Stream(4 種常見方式) 從集合創建(最常用):list.stream()(串行)、list.parallelStream()(並行); 從數組創建:Arrays.stream(數組) 或 Stream.of(數組元素); 從值創建:Stream.of(1,2,3,4); 生成無限流:Stream.generate(()->Math.random())(需用 limit 終止)。 示例:

// 1. 集合創建 List stream1 = list.stream();

// 2. 數組創建 String[] arr = {"x", "y", "z"}; Stream stream2 = Arrays.stream(arr);

// 3. 直接創建 Stream stream3 = Stream.of(10, 20, 30);

// 4. 無限流(生成 5 個隨機數) Stream randomStream = Stream.generate(Math::random).limit(5); AI構建項目

  1. 第二步:中間操作(常用 API) 之前學過的 filter、sorted、limit 都是中間操作,再補充幾個核心:

map(Function):將元素映射為另一種類型(如整數轉字符串、對象取屬性); distinct():去重(基於 equals() 方法); skip(long n):跳過前 n 個元素。 示例(組合中間操作):

List users = Arrays.asList( new User("張三", 17), new User("李四", 22), new User("王五", 19), new User("李四", 22) );

// 篩選成年用户 → 去重 → 提取姓名 → 跳過前 1 個 → 限制 1 個 users.stream() .filter(u -> u.getAge() >= 18) // 成年:李四、王五、李四 .distinct() // 去重:李四、王五 .map(User::getName) // 提取姓名:"李四"、"王五" .skip(1) // 跳過第一個:"王五" .limit(1) // 保留 1 個:"王五" .forEach(System.out::println); // 輸出:王五 AI構建項目

  1. 第三步:終端操作(常用 API) 遍歷:forEach(Consumer)(無返回值,直接消費元素); 收集:collect(Collector)(轉為集合、Map 等,如 Collectors.toList()); 統計:count()(元素個數)、average()(平均值,僅數值流)、max(Comparator)(最大值); 判斷:anyMatch(Predicate)(是否存在符合條件的元素)、allMatch(Predicate)(是否所有元素符合)。 示例(終端操作):

List numbers = Arrays.asList(1,2,3,4,5,6);

// 1. 收集為集合 List evenList = numbers.stream() .filter(num -> num % 2 == 0) .collect(Collectors.toList()); // [2,4,6]

// 2. 統計個數 long evenCount = numbers.stream() .filter(num -> num % 2 == 0) .count(); // 3

// 3. 判斷是否存在大於 5 的元素 boolean hasGt5 = numbers.stream() .anyMatch(num -> num > 5); // true

// 4. 求最大值 Optional max = numbers.stream() .max(Integer::compare); // 6 AI構建項目

四、Stream 的核心價值 簡化代碼:用鏈式調用替代繁瑣的循環、判斷,代碼行數大幅減少; 提高效率:惰性執行 + 並行處理,底層優化(如流水線操作、減少中間集合創建); 易維護:聲明式編程讓邏輯更清晰,可讀性、可維護性提升; 功能強大:內置豐富的中間 / 終端操作,支持篩選、排序、映射、統計等常見場景。 五、關鍵注意事項 不修改原數據源:所有操作都是 “只讀”,原始集合 / 數組不會被改變; Stream 不可複用:終端操作後 Stream 失效,需重新創建(如下方錯誤示例); Stream stream = numbers.stream().filter(num -> num % 2 == 0); stream.forEach(System.out::println); // 終端操作,stream 失效 stream.count(); // 報錯:IllegalStateException(stream 已被消費) AI構建項目 並行流的線程安全:並行處理時,若中間操作有狀態(如自定義 map 中修改外部集合),需保證線程安全(推薦用無狀態操作); 空指針處理:Stream 不直接處理 null 元素,若數據源有 null,需提前用 filter(Objects::nonNull) 過濾。 總結 是什麼:Java 8 新增的 “元素序列”,用於聲明式處理數據源,不存儲、不修改原數據; 核心結構:創建 Stream → 中間操作(鏈式)→ 終端操作(觸發執行); 核心特性:惰性執行、並行支持、聲明式編程、無狀態 / 有狀態操作; 價值:簡化代碼、提高效率、易維護,是 Java 集合處理的 “升級方案”; 使用場景:集合篩選、排序、映射、統計等數據處理場景(替代傳統循環)。 ———————————————— 版權聲明:本文為CSDN博主「忘記926」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。 原文鏈接:https://blog.csdn.net/2403_87639415/article/details/155539279