目錄
1、用來做什麼的?
2、都有哪些用法?
3、源碼怎麼實現的?
4、總結
最近一段時間比較忙,也不知道都在做些什麼。五一期間本來打算寫一篇的,但是一直有各種事情拖着也沒寫下來。今天繼續是計劃內的一篇文章collector。
1、用來做什麼的?
collectors直接翻譯就是收集器。主要的作用是就是將流中的數據進行收集整理。collectors主要還是配合stream來使用。平常的話也不會用到。
2、都有哪些用法?
Collectors可以幫我們完成的事情,例如:分組、排序(支持多字段排序)、最大值、最小值、平均值,簡單的來說,以前我們在數據上面用sql 去完成的聚合相關的操作,Collectors 都可以完成。可以參照stream那一篇。
3、源碼怎麼實現的?
Collectors到底是怎麼實現的呢?現在來看一下源碼,一起學習一下。
先看一下collect需要傳入的參數都有哪些。
可以看到有兩種實現
一種實現就是傳入三個函數。
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
另外一種實現就是傳入一個collector。其實沒有本質上的區別。
list.stream().collect(Collectors.toList())
先看看最簡單的Collectors.toSet()實現。
public static <T>
Collector<T, ?, Set<T>> toSet() {
return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
(left, right) -> { left.addAll(right); return left; },
CH_UNORDERED_ID);
}
從上面代碼可以看到toSet返回了一個CollectorImpl,CollectorImpl實現和上面的三個函數差不多。只有一個參數不一樣。
CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Set<Characteristics> characteristics) {
this(supplier, accumulator, combiner, castingIdentity(), characteristics }
下面開始理解這個三個函數到底都在做什麼?
Supplier<A> supplier, supplier是主要創建一個新的對象返回。一般用來返回一個容器對象。
BiConsumer<A, T> accumulator, 主要是用來累加合併,將新的T和A進行融合。一般來說T放入a的集合中。
BinaryOperator<A> combiner,主要是用來對多線程的時候進行組裝。
Set<Characteristics> characteristics 最後一個參數主要是描述集合的特性,需要做什麼樣的操作。等下會有介紹。
具體流程是什麼樣的我們自己來實現一下
List<String> list = Lists.newArrayList();
list.add("香菜");
list.add("聊遊戲");
Supplier<Set<String>> supplier = ()-> new HashSet<>();
BiConsumer<Set<String>, String> accumulator = (set, s) -> set.add(s);
BiConsumer<Set<String>, Set<String>> combiner = (left,right)->{left.addAll(right);};
Set<String> collect = list.stream().parallel().collect(supplier, accumulator, combiner);
System.out.println(collect);
我們到底做了什麼?
R result = supplier.get();
for (T element : this stream)
accumulator.accept(result, element);
return result;
多線程的情況下就像下面這張圖。
而collect中只有一個參數,那就是Collector對象,java.util.stream.Collector 這是一個接口,其功能是將流處理的結果,匯聚處理成最終的一個可變對象(容器)。 這個接口有5個方法:
Supplier supplier(); 創建一個結果容器
BiConsumer accumulator(); 將元素合併到結果容器中
BinaryOperator combiner(); 將兩個結果容器合併
Function finisher(); 最終操作
Set characteristics();返回一個固定的特徵集合
特徵集合:
/**當前Collector支持併發,一般情況下UNORDERED也會一起放在characteristics中*/
CONCURRENT,
/** 當前Collector對操作元素是不會關心順序的的 */
UNORDERED,
/**當前Collector沒有Finisher*/
IDENTITY_FINISH
看了源碼應該瞭解是怎麼回事了,具體的實現可以參照Collector 的實現,so easy。
4、總結
Collectors一個常用的collector工廠,這個工廠就是collect中常用的收集方式的實現。記住最重要的那張圖,一切就迎刃而解了。
人生不像做飯,不能等萬事俱備了才下鍋。
————————————————
原文鏈接:https://blog.csdn.net/perfect2011/article/details/106065050