首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java Stream API 完全指南:從創建到收集器的實戰詳解

     編輯:Java 程式設計入門

Java 8 引入的 java.util.stream.Stream 為集合處理帶來聲明式、函數式風格,極大簡化了篩選、轉換、聚合等操作。本文系統梳理 Stream 特性、創建方式、中間/終端操作、並行流、收集器、常見陷阱與第三方擴展,助你寫出優雅高效的集合代碼。

核心特性

創建 Stream 的 8 種方式

  1. Collection.stream() / parallelStream()
  2. Arrays.stream(T[]) / Arrays.stream(int[])
  3. 靜態工廠:Stream.of()、IntStream.range()、Stream.iterate()、Stream.generate()
  4. BufferedReader.lines() 文件行流
  5. Files.list/find/walk 路徑流
  6. Random.ints() 隨機數流
  7. 第三方:BitSet.stream()、Pattern.splitAsStream()、JarFile.stream()
  8. 底層:StreamSupport.stream(Spliterator)

中間操作

特性說明
不存儲數據基於數據源(集合、陣列、IO)透過管道傳遞元素
函數式操作不修改源,filter 不刪除原集合元素
延遲執行中間操作(filter/map)僅記錄,終端操作才真正執行
可短路limit/findFirst 遇無限流也能在有限步完成
單次消費元素只能遍歷一次,需重新獲取 Stream 再用
操作說明示例
distinct()去重(equals)Stream.of("a","b","a").distinct() → [a,b]
filter(Predicate)篩選符合條件元素IntStream.range(1,10).filter(i->i%2==0) → [2,4,6,8]
map(Function)一對一轉換,可改類型Stream.of('a','b').map(c->c.hashCode()) → [97,98]
flatMap(Function)一對多扁平化lines.flatMap(line->Arrays.stream(line.split(" ")))
limit(n)截取前 n 個IntStream.range(1,100).limit(5) → [1..5]
peek(Consumer)消費但不改變流(調試用).peek(System.out::println)
sorted() / sorted(Comparator)排序.sorted((a,b)->a-b)
skip(n)跳過前 n 個.skip(3)

終端操作

分類操作說明
匹配allMatch/anyMatch/noneMatch斷言全滿足/任一滿足/全不滿足,空流 allMatch=true, anyMatch=false, noneMatch=true
count()元素個數(實現為 mapToLong(e->1L).sum())
findFirst() / findAny()返回首個/任一元素(Optional),並行流 findAny 更快但結果不確定
遍歷forEach(Consumer)不保證順序,有序流用 forEachOrdered
forEachOrdered保證遇見順序執行
極值max(Comparator) / min(Comparator)返回 Optional
歸約reduce三種重載:無初值/有初值/並行專用 combiner,累加器需滿足結合律
收集collect(Collector)最強終端操作,見下節收集器詳解
轉陣列toArray()返回 Object[] 或類型陣列

收集器:Collectors 工具類精華

// 轉集合
.toList() / .toSet() / .toCollection(ArrayList::new)

// 字串連接
.joining() / .joining(",") / .joining(",", "[", "]")

// 分組 / 分區
.groupingBy(User::getDept)
.groupingBy(User::getDept, counting())
.partitioningBy(user -> user.getAge() > 18)

// 聚合
.counting() / .summingInt(User::getAge) / .averagingDouble(User::getScore)
.maxBy(Comparator.comparing(User::getAge)) / .minBy(...)
.summarizingInt(User::getAge) // 返回 IntSummaryStatistics

// 降級/轉換
.mapping(User::getName, toList())
.collectingAndThen(toList(), Collections::unmodifiableList)

// 自定義 Collector
Collector.of(supplier, accumulator, combiner, finisher, characteristics)

並行流與性能

  • 默認串行,parallelStream() 或 .parallel() 開啟。
  • 無狀態、非干擾、關聯性滿足時,並行結果與串行一致。
  • 有序流並行可能降低性能(distinct、sorted、limit),可 .unordered() 優化。
  • 小數據量、高計算密度任務適合並行;IO 密集、大量同步鎖反而變慢。

常見陷阱

  1. 重複消費:stream.forEach(...); stream.count(); → IllegalStateException,需重新獲取流。
  2. 修改源集合:終端操作執行期間修改非併發集合 → ConcurrentModificationException。
  3. 有狀態 Lambda:並行下結果不確定,保持純函數。
  4. 副作用濫用:forEach(list::add) 非線程安全,改用 collect(toList())。
  5. 裝箱開銷:基本類型流(IntStream)避免裝箱,性能提升明顯。

第三方擴展推薦

  • protonpack:takeWhile、zip、unfold、MapStream 等缺失操作。
  • java8-utils:實用輔助方法補充。

總結

Stream API 讓集合處理從「怎麼做」轉向「做什麼」,配合 Lambda 與收集器,代碼更簡潔、可讀、易並行。掌握中間/終端操作分類、收集器組合、並行適用場景與常見坑,是現代 Java 開發必備技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved