Collector與Collectors之間的關系
作為collect方法的參數,Collector是一個接口,它是一個可變的匯聚操作,將輸入元素累計到一個可變的結果容器中;它會在所有元素都處理完畢后,將累積的結果轉換為一個最終的表示(這是一個可選操作);
Collectors本身提供了關於Collector的常見匯聚實現,Collectors的內部類CollectorImpl實現了Collector接口,Collectors本身實際上是一個工廠。
自定義Collector
public interface Collector {
Supplier supplier();
BiConsumer accumulator();
BinaryOperator combiner();
Function finisher();
Set characteristics();
}
Collector主要定義了容器的類型,添加元素的方法,容器合並的方法還有輸出的結果。
supplier就是生成容器
accumulator是添加元素
combiner是合並容器
finisher是輸出的結果
characteristics是定義容器的三個屬性(三個枚舉值),包括是否有明確的finisher,是否需要同步,是否有序。
CONCURRENT(集合的操作需要同步):表示中間結果只有一個,即使在並行流的情況下。所以只有在並行流且收集器不具備CONCURRENT特性時,combiner方法返回的lambda表達式才會執行(中間結果容器只有一個就無需合並)
UNORDER(集合是無序的):表示流中的元素無序。
IDENTITY_FINISH(不用finisher):表示中間結果容器類型與最終結果類型一致,此時finiser方法不會被調用
其中這里的泛型所表示的含義是:
T:表示流中每個元素的類型。
A:表示中間結果容器的類型。
R:表示最終返回的結果類型。
例如: Collectors里面有個tolist()方法,返回一個收集器如下
Collector(ArrayList::new,List::add,List::addAll,IDENTITY_FINISH)
可以看到,先是一個ArrayList的實例化,然后是添加元素使用List的add方法,容器合並就是addAll方法。這里沒有finisher,原因是最終結果要的就是List,finisher就是返回容器。但是stream.collect()方法如何得知?就是通過枚舉類型得到的
定義好collector,最終傳參進stream的collect方法里,這個終結的操作最后會通過你定義的統計和收集的操作進行收集。
Collectors
1. toCollection
public static > Collector toCollection(Supplier collectionFactory)
將數據轉換為指定的集合
Collection c = stream.collect(toCollection(),ArrayList::new);Collection c = stream.collect(toCollection(),HashSet::new);
2. toList
public static Collector> toList()
將流中所有項目收集到一個List
List l=stream.collect(toList());
3. toSet
public static Collector> toSet()
將流中所有項目收集到一個Set
Set s = stream.collect(toSet());
4. joining
public static Collector joining()
public static Collector joining(CharSequence delimiter)
public static Collector joining(CharSequence delimiter,CharSequence prefix,CharSequence suffix)
將流中每個元素調用toString方法拼接
String s = stream.collect(joining(" , ");
5. mapping
public static Collector mapping(Function super T,? extends U> mapper,
Collector super U,A,R> downstream)
T - the type of the input elements
U - type of elements accepted by downstream collector
A - intermediate accumulation type of the downstream collector
R - result type of collector
mapping() 收集器在多級別的 reducing 中最有用,比如在groupingBy或partitioningBy的下游。
例如,給定一個人的流,在每個城市中積累最后的名字的集合。
Map> lastNamesByCity = people.stream() .collect(groupingBy(Person::getCity,mapping(Person::getLastName, toSet())));
6. collectingAndThen
public static Collector collectingAndThen(Collector downstream,
Function finisher)
T - the type of the input elements
A - intermediate accumulation type of the downstream collector
R - result type of the downstream collector
RR - result type of the resulting collector
包裹一個收集器,對其結果應用轉換函數
List people = people.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));
7. counting
public static Collector counting()
計算流中數量
long l=stream.collect(counting());
8. minBy
public static Collector> minBy(Comparator super T> comparator)
篩選流中最小元素的Optional,流為空則Optional.empty()
Optional o = stream.collect(minBy(Comparator.comparingInt(T::getXX)));
9. maxBy
public static Collector> maxBy(Comparator super T> comparator)
篩選流中最大元素的Optional,流為空則Optional.empty()
Optional o = stream.collect(maxBy(Comparator.comparingInt(T::getXX)));
10. summingInt / summingLong / summingDouble
public static Collector summingInt(ToIntFunction super T> mapper)
public static Collector summingLong(ToLongFunction super T> mapper)
public static Collector summingDouble(ToDoubleFunction super T> mapper)
收集流中Integer / summingLong / summingDouble 屬性的統計值
IntSummaryStatistics i=stream.collect(summarizingInt(T::getXX));
11. averagingInt / averagingLong / averagingDouble
public static Collector averagingInt(ToIntFunction super T> mapper)
public static Collector averagingLong(ToLongFunction super T> mapper)
public static Collector averagingDouble(ToDoubleFunction super T> mapper)
計算流中Integer屬性的平均值
double d=stream.collect(averagingInt(T::getXX));
12. reducing
public static Collector reducing(T identity,BinaryOperator op)
public static Collector> reducing(BinaryOperator op)
public static Collector reducing(U identity,
Function super T,? extends U> mapper,
BinaryOperator op)
從初始值開始,利用BinaryOperator與流中每個元素相結合,從而將流歸約成單個值
int i = stream.collect(reducing(0, T::getXX, Integer :: sum));
13. groupingBy
public static Collector>> groupingBy(Function super T,? extends K> classifier)
public static Collector> groupingBy(Function super T,? extends K> classifier,
Collector super T,A,D> downstream)
public static > Collector groupingBy(Function super T,? extends K> classifier,
Supplier mapFactory,
Collector super T,A,D> downstream)
T - the type of the input elements
K - the type of the keys
A - the intermediate accumulation type of the downstream collector
D - the result type of the downstream reduction
M - the type of the resulting Map
根據流中一個屬性的值做分組,並以該屬性為Map的一個Key
Map> namesByCity
= people.stream().collect(groupingBy(Person::getCity,
mapping(Person::getLastName, toSet())));
Map> namesByCity
= people.stream().collect(groupingBy(Person::getCity, TreeMap::new,
mapping(Person::getLastName, toSet())));
14. partitioningBy
public static Collector>> partitioningBy(Predicate super T> predicate)
public static Collector> partitioningBy(Predicate super T> predicate, Collector super T,A,D> downstream)
根據對流中的每個元素的應用謂詞的結果進行分區(true,false)