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

Java 函數式編程(十):Collector 搜集器深度解析

     編輯:Java 相關知識

前言

在 Stream 流程的最後一步,collect() 方法配合 Collectors 工具類,將流元素匯聚為各種數據結構(List、Set、Map、字符串等)。本文深入剖析 Collector 的核心機制、常用靜態工廠方法,以及如何自定義 Collector 滿足複雜聚合需求。

Collector 接口核心契約

Collector<T, A, R> 定義了三大核心操作:

  • supplier():創建可變結果容器(如 ArrayList::new)
  • accumulator():將元素累加到容器(如 List::add)
  • combiner():合併兩個容器(併行流時用)
  • finisher():最終轉換(如 Collections::unmodifiableList)
  • characteristics():特性標識(CONCURRENT、UNORDERED、IDENTITY_FINISH)

Collectors 常用工廠方法速查

分類方法返回類型典型場景
集合收集toList()List<T>最常用,保留順序與重複
toSet()Set<T>去重,無序
toCollection(Supplier)Collection<T>指定具體集合類型(如 LinkedList)
Map 收集toMap(keyMapper, valueMapper)Map<K,V>鍵值非空、鍵唯一
toMap(..., mergeFn)Map<K,V>鍵衝突時合併值
toConcurrentMap(...)ConcurrentMap併行環境下高性能
字符串拼接joining()String無分隔符直接拼接
joining(delimiter)String指定分隔符(如 CSV)
歸約統計counting()Long元素計數
summingInt/Long/Double(mapper)Integer/Long/Double數值屬性求和
averagingInt/Long/Double(mapper)Double計算平均值
summarizingInt/Long/Double(mapper)IntSummaryStatistics 等一次獲取 count、sum、min、max、average
分組與分區groupingBy(classifier)Map<K, List<T>>單級分組
groupingBy(classifier, downstream)Map<K, D>多級分組或自定義下游收集
partitioningBy(predicate)Map<Boolean, List<T>>二分分區(真/假)

進階實戰:多級分組與下游收集器

按部門再按性別分組,並統計每組平均薪資:

Map<String, Map<String, Double>> result = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getDept,
        Collectors.groupingBy(
            Employee::getGender,
            Collectors.averagingDouble(Employee::getSalary)
        )
    ));

自定義 Collector:實現「去重並保留首次出現順序」

public static <T> Collector<T, ?, List<T>> distinctPreservingOrder() {
    return Collector.of(
        ArrayList::new,                          // supplier
        (list, item) -> { if (!list.contains(item)) list.add(item); }, // accumulator
        (list1, list2) -> {                      // combiner
            list2.stream().filter(e -> !list1.contains(e)).forEach(list1::add);
            return list1;
        },
        Collections::unmodifiableList            // finisher
    );
}

使用:list.stream().collect(distinctPreservingOrder())

性能提示

  • 併行流優先用 toConcurrentMap、groupingByConcurrent 避免合併開銷。
  • 大數據量下,summarizingXxx 比多次遍歷高效得多。
  • 避免在 accumulator 裡做耗時操作,保持無副作用。

總結

Collector 是 Stream 終端操作的核心,Collectors 提供了豐富的開箱即用工廠,覆蓋 90% 以上場景。掌握其組合規則(downstream collector)與自定義機制,能優雅解決複雜聚合需求。下一篇將探討 Comparator 在函數式排序中的新用法。

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