Collector常見用法
常用形式為: .collect(Collectors.toList())
collect()是Stream的方法
Collectors 是收集器Collector 的工廠方法,提供了一些常用的收集器
|
比如
常用收集器概要
收集器 | 行為 |
---|---|
toList() |
將元素收集到一個 List 中。 |
toSet() |
將元素收集到一個 Set 中。 |
toCollection() |
將元素收集到一個 Collection 中。 |
toMap(...) |
將元素收集到一個 Map 中,依據提供的映射函數將元素轉換為鍵/值。 |
summingInt(ToIntFunction<? super T>) |
給定值序列進行求和(還有 long 和 double 版本) |
summarizingInt(ToIntFunction<T>) |
給定值序列計算統計信息 sum 、 min 、 max 、 count 和 average (還有 long 和 double 版本) |
reducing(...) |
用於歸約計算(通常用作下游收集器,比如用於 groupingBy 或者partitioningBy 下游 ) |
partitioningBy(...) |
按照predicate分為兩組 |
groupingBy(...) |
將元素分組 |
maxBy(Comparator<? super T> comparator) | 最大值 |
minBy(Comparator<? super T> comparator) |
最小值 |
mapping(Function<T,U>, Collector) |
將提供的映射函數應用於每個元素,並使用指定的下游收集器(通常用作下游收集器本身,比如用於 groupingBy )進行處理。 |
joining() |
假設元素為 String 類型,將這些元素聯結到一個字符串中(或許使用分隔符、前綴和后綴)。 |
counting() |
計算元素數量。(通常用作下游收集器。) |
averagingInt(ToIntFunction<? super T>) | 平均數 (還有 long 和 double 版本) |
收集器參數列表
toList()
|
toSet()
|
toCollection(Supplier<C>)
|
counting()
|
collectingAndThen(Collector<T, A, R>, Function<R, RR>)
|
summingInt(ToIntFunction<? super T>)
summingLong(ToLongFunction<? super T>)
summingDouble(ToDoubleFunction<? super T>)
|
maxBy(Comparator<? super T>)
|
minBy(Comparator<? super T>)
|
reducing(BinaryOperator<T>)
reducing(T, BinaryOperator<T>)
reducing(U, Function<? super T, ? extends U>, BinaryOperator<U>)
|
joining()
joining(CharSequence)
joining(CharSequence, CharSequence, CharSequence)
|
mapping(Function<? super T, ? extends U>, Collector<? super U, A, R>)
|
toMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>)
toMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>, BinaryOperator<U>)
toMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>, BinaryOperator<U>, Supplier<M>)
toConcurrentMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>)
toConcurrentMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>, BinaryOperator<U>)
toConcurrentMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>, BinaryOperator<U>, Supplier<M>)
|
groupingBy(Function<? super T, ? extends K>)
groupingBy(Function<? super T, ? extends K>, Supplier<M>, Collector<? super T, A, D>)
groupingBy(Function<? super T, ? extends K>, Collector<? super T, A, D>)
groupingByConcurrent(Function<? super T, ? extends K>)
groupingByConcurrent(Function<? super T, ? extends K>, Supplier<M>, Collector<? super T, A, D>)
groupingByConcurrent(Function<? super T, ? extends K>, Collector<? super T, A, D>)
|
partitioningBy(Predicate<? super T>)
partitioningBy(Predicate<? super T>, Collector<? super T, A, D>)
|
averagingDouble(ToDoubleFunction<? super T>)
averagingInt(ToIntFunction<? super T>)
averagingLong(ToLongFunction<? super T>)
|
summarizingDouble(ToDoubleFunction<? super T>)
summarizingInt(ToIntFunction<? super T>)
summarizingLong(ToLongFunction<? super T>)
|
收集器詳解
Collector
T - 輸入類型A - 在收集過程中用於累積部分結果的對象類型R - 返回類型
mutable reduction的一些場景:
將元素聚集到集合中
使用StringBuilder連接字符串
計算有關元素的匯總信息,如sum、min、max或平均值
計算“主表”摘要,如“賣方的最大價值交易”等
類Collectors提供了許多常見的reduce實現
|
收集器構成
收集器是由四個函數約定構成,它們一起工作,將條目匯集到一個可變的結果容器中,並可選擇性地對結果執行最終轉換。
1. 創建一個新的結果容器(supplier())
2. 將一個新的數據元素合並到一個結果容器中(accumulator())
3. 將兩個結果容器合並成一個(combiner())
(非必然運行 可能在並行流且Collector不具備CONCURRENT 時執行的 )
4. 在容器上執行一個可選的最終轉換 (finisher())
(非必然運行 中間結果與最終結果類型是否一致決定是否運行 IDENTITY_FINISH用來標志 )
|
屬性特征字段
特征值是Collector的特征值,用於描述Collecto本身r的,不是其他含義 |
Set<Characteristics> characteristics() 方法可以訪問 |
Collector.Characteristics CONCURRENT
表示中間結果只有一個,即使在並行流的情況下
所以只有在並行流且收集器不具備CONCURRENT特性時,combiner方法返回的lambda表達式才會執行
如果收集器沒有標為UNORDERED,那它僅在用於無序數據源時才可以並行歸約
|
Collector.Characteristics UNORDERED
表示不承諾按照操作順序排列
|
Collector.Characteristics IDENTITY_FINISH 表示中間結果容器類型與最終結果類型一致,此時finiser方法不會被調用 |
靜態工廠方法
根據提供的給定條件創建 Collector
Collector 就是歸約運算操作的一種抽象
首先要理解歸約reduce的含義 也就是歸納轉換成另外一種形式
想要進行歸約運算,你先給出一個初始容器,作為中間結果容器
然后再給出迭代運算邏輯 也就是要如何歸約 歸約的邏輯 就是在這里 結果計算到中間結果容器中
針對於並行計算還需要一個合並的方式
中間結果肯定是為了方便計算,如果你最終想要的不是這種類型,我還可以給你轉換下
|
Collector用 類型TAR 和四個方法將歸約的過程邏輯化
T - 輸入類型
A - 在收集過程中用於累積部分結果的對象類型
R - 返回類型
|
Supplier<A> supplier(); 所以此方法提供了一個保存中間結果的對象 類型是A
BiConsumer<A, T> accumulator(); 不斷迭代運算操作結果累計到中間結果上 類型為A 流類型為T
Function<A, R> finisher(); 最終的結果為A 還要根據實際情況是否轉換為R
BinaryOperator<A> combiner(); 用於合並計算
|
Collector工廠Collectors
提供了Collector的一些常用實現 比如
// 獲取所有的name轉換到List<String>中 List<String> list = people.stream().map(Person::getName).collect(Collectors.toList()); // 獲取所有的name轉換到Set<String>中 Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));
// 元素轉換為String 並且將他們通過", " 連接起來 String joined = things.stream() .map(Object::toString) .collect(Collectors.joining(", "));
//計算員工薪水之和
int total = employees.stream() .collect(Collectors.summingInt(Employee::getSalary)));
// 按照部門對員工進行分組 Map<Department, List<Employee>> byDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment));
// 計算部門薪資和 Map<Department, Integer> totalByDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.summingInt(Employee::getSalary)));
// 按照成績是否通過把學生分為兩組 Map<Boolean, List<Student>> passingFailing = students.stream() .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
Collectors 中有一個靜態內部類CollectorImpl 實現了CollectorImpl
預置的一些收集器都是通過CollectorImpl 返回的
/** * Simple implementation class for {@code Collector}. * * @param <T> the type of elements to be collected * @param <R> the type of the result */
static class CollectorImpl<T, A, R> implements Collector<T, A, R> { private final Supplier<A> supplier; private final BiConsumer<A, T> accumulator; private final BinaryOperator<A> combiner; private final Function<A, R> finisher; private final Set<Characteristics> characteristics;
CollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner, Function<A,R> finisher, Set<Characteristics> characteristics) { this.supplier = supplier; this.accumulator = accumulator; this.combiner = combiner; this.finisher = finisher; this.characteristics = characteristics; } CollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner, Set<Characteristics> characteristics) { this(supplier, accumulator, combiner, castingIdentity(), characteristics); } @Override public BiConsumer<A, T> accumulator() { return accumulator; } @Override public Supplier<A> supplier() { return supplier; } @Override public BinaryOperator<A> combiner() { return combiner; } @Override public Function<A, R> finisher() { return finisher; } @Override public Set<Characteristics> characteristics() { return characteristics; } }
Collectors中內置的 關於Collector characteristics 特性的組合值
看一個例子
Collector<T, ?, List<T>> toList() { return new CollectorImpl<>( (Supplier<List<T>>) ArrayList::new, List::add, (left, right) -> { left.addAll(right); return left; }, CH_ID); }
TAR分別是 T ? List<T> 也就是處理元素為T類型 返回結果為List<T> 中間結果隨意
ArrayList::new 返回List<T> 作為中間結果,顯然,跟返回結果一樣,不需要調用finisher了
歸約方式為 使用List.add方法不斷地將集合中的元素添加到中間結果中
合並方式為直接將一個List addAll到另一個list 並且返回最終結果
因為不需要調用finisher 設置下特征 CH_ID
所以說只要按規矩實現了四個方法以及設置characteristics 就可以實現一個Collector
你可以使用Stream中
調用Collectors 提供的一些Collector 或者你自己定義的
你還可以使用Stream中
直接傳遞參數,顯然並不是很直觀 建議能不用就別用了