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

Java 8 聚合操作(Stream API)核心指南

     編輯:Java 相關知識

Java 8 引入 Stream API,通過聚合操作實現集合的聲明式處理。本文系統講解 Stream 創建、中間/終端操作、並行流、收集器、最佳實踐。

Stream 創建入口


// Collection 直接創建
List list = ...;
Stream stream = list.stream();           // 串行
Stream pStream = list.parallelStream();  // 並行

// 數組創建
Stream aStream = Arrays.stream(array);
Stream arrStream = Arrays.stream(intArray); // 基本類型流

// 靜態工廠
Stream.of("a", "b", "c");
Stream.iterate(0, n -> n + 2).limit(10);  // 無限流
Stream.generate(Math::random).limit(5);   // 無限流

// 基本類型專用流
IntStream.range(0, 100);
LongStream.of(1L, 2L, 3L);
DoubleStream.generate(() -> Math.random());

操作分類:管道模型

數據源 → 中間操作 (0..N) → 終端操作 (1)
           惰性求值            觸發執行

中間操作:轉換與過濾

操作功能特點
filter(Predicate)過濾元素保留滿足條件者
map(Function)一對一轉換類型可變 T→R
flatMap(Function)一對多扁平化流扁平化 Stream>
distinct()去重基於 equals,有狀態
sorted() / sorted(Comparator)排序有狀態,需緩存所有元素
peek(Consumer)側效觀察調試用,不改變流
limit(n) / skip(n)截取/跳過短路操作

終端操作:產生結果

分類操作返回值
遍歷/匹配forEach(Consumer)void
forEachOrdered(Consumer)void (保序)
anyMatch/allMatch/noneMatch(Predicate)boolean (短路)
findFirst/findAny()Optional (短路)
歸約/聚合reduce(BinaryOperator)Optional
reduce(identity, BinaryOperator)T
collect(Collector)R (可變容器)
count()long
數值計算sum/average/min/max()基本類型/Optional
summaryStatistics()IntSummaryStatistics 等
toArray()Object[]

實戰範例:Person 集合處理


List persons = ...;

// 1. 篩選成年男性,按年齡降序,取前 3 名字
List top3 = persons.stream()
    .filter(p -> p.getAge() >= 18)
    .filter(p -> p.getGender() == Sex.MALE)
    .sorted(Comparator.comparing(Person::getAge).reversed())
    .limit(3)
    .map(Person::getName)
    .collect(Collectors.toList());

// 2. 分組統計:性別 → 平均年齡
Map avgAge = persons.stream()
    .collect(Collectors.groupingBy(Person::getGender,
        Collectors.averagingInt(Person::getAge)));

// 3. 分區:成年/未成年 → 名字列表
Map> partitioned = persons.stream()
    .collect(Collectors.partitioningBy(p -> p.getAge() >= 18,
        Collectors.mapping(Person::getName, Collectors.toList())));

// 4. 並行處理大數據集
long adultCount = persons.parallelStream()
    .filter(p -> p.getAge() >= 18)
    .count();

收集器進階


// 自定義收集器:字符串連接 (已內置 Collectors.joining)
Collector joining = Collector.of(
    StringBuilder::new,
    (sb, s) -> sb.append(s),
    (sb1, sb2) -> sb1.append(sb2),
    StringBuilder::toString
);

// 分組 + 下游收集器
Map> byGender = persons.stream()
    .collect(Collectors.groupingBy(Person::getGender,
        Collectors.mapping(p -> p.getName(), Collectors.toList())));

並行流注意事項

  • 無副作用: Lambda 必須純函數,不修改共享狀態
  • 數據源可分割: ArrayList/數組分割快,LinkedList 分割慢
  • 計算密集型受益: CPU 密集任務加速明顯,IO 密集反而可能變慢
  • 公共 ForkJoinPool: 所有並行流共享,長任務可能阻塞其他並行流

Stream vs Iterator

特性IteratorStream
控制權開發者手動 next()框架內部自動迭代
執行模式僅順序可並行
操作風格命令式聲明式/函數式
數據源修改可邊遍歷邊修改 (風險)不修改源,產生新流
惰性求值無中間操作惰性,終端觸發

避坑指南

  • ❌ 重複使用流:流只能消費一次,需重新獲取
  • ❌ 在流中修改底層集合:ConcurrentModificationException
  • ❌ 基本類型流裝箱開銷:優先用 IntStream/LongStream/DoubleStream
  • ❌ 並行流處理有序敏感操作:findFirst()、limit() 會強制保序降低並行度
  • ✅ 善用 Collectors 內置收集器,減少自定義
  • ✅ 大數據集優先 parallelStream(),小數據集串行更快
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved