java 8流自定义收集器_Java 8编写自定义收集器简介
java 8流自定義收集器
Java 8引入了收集器的概念。 大多數(shù)時候,我們幾乎不使用Collectors類中的工廠方法,例如collect(toList()) , toSet()或其他更有趣的方法,例如counting()或groupingBy() 。 實際上,沒有多少人真正去研究如何定義和實現(xiàn)收集器。 讓我們從分析Collector<T, A, R>真正含義及其工作原理開始。
Collector<T, A, R>充當流的“接收器 ” –流將項(一個接一個)推入收集器,最后應產(chǎn)生一些“ 收集 ”值。 在大多數(shù)情況下,這意味著通過累積元素或將流減少為更小的內容(例如, counting()很少的元素的toList()收集器)來構建集合(如toList() )。 每個收集器都接受類型T項,并產(chǎn)生類型R聚合(累積)值(例如R = List<T> )。 泛型A簡單定義了中間可變數(shù)據(jù)結構的類型,在此期間,我們將使用它來累積T型項。 類型A可以但不必與R相同-簡單來說,我們用來從輸入Stream<T>收集項目的可變數(shù)據(jù)結構可以不同于實際的輸出收集/值。 話雖如此,每個收集器都必須實現(xiàn)以下方法:
interface Collector<T,A,R> {Supplier<A> supplier()BiConsumer<A,T> acumulator() BinaryOperator<A> combiner() Function<A,R> finisher()Set<Characteristics> characteristics() }- supplier()返回一個函數(shù),該函數(shù)創(chuàng)建一個累加器實例–可變數(shù)據(jù)結構,我們將使用該函數(shù)來累加類型T輸入元素。
- accumulator()返回一個函數(shù),該函數(shù)將累加累加器和類型T一項,即累加累加器。
- combiner()用于將兩個累加器合并為一個。 它在并行執(zhí)行收集器時使用,首先拆分輸入Stream<T>并首先獨立收集部分。
- finisher()使用累加器A并將其轉換為R類型的結果值,例如collection。 所有這些聽起來都很抽象,所以讓我們做一個簡單的例子。
顯然,Java 8沒有為Guava提供ImmutableSet<T>的內置收集器。 但是,創(chuàng)建一個非常簡單。 請記住,為了迭代地構建ImmutableSet我們使用ImmutableSet.Builder<T> –這將是我們的累加器。
import com.google.common.collect.ImmutableSet;public class ImmutableSetCollector<T> implements Collector<T, ImmutableSet.Builder<T>, ImmutableSet<T>> {@Overridepublic Supplier<ImmutableSet.Builder<T>> supplier() {return ImmutableSet::builder;}@Overridepublic BiConsumer<ImmutableSet.Builder<T>, T> accumulator() {return (builder, t) -> builder.add(t);}@Overridepublic BinaryOperator<ImmutableSet.Builder<T>> combiner() {return (left, right) -> {left.addAll(right.build());return left;};}@Overridepublic Function<ImmutableSet.Builder<T>, ImmutableSet<T>> finisher() {return ImmutableSet.Builder::build;}@Overridepublic Set<Characteristics> characteristics() {return EnumSet.of(Characteristics.UNORDERED);} }首先,仔細研究泛型。 我們的ImmutableSetCollector接受類型T輸入元素,因此它適用于任何Stream<T> 。 最后,將產(chǎn)生預期的ImmutableSet<T> 。 ImmutableSet.Builder<T>將成為我們的中間數(shù)據(jù)結構。
- supplier()返回創(chuàng)建新ImmutableSet.Builder<T>的函數(shù)。 如果您不熟悉Java 8中的lambda,則ImmutableSet::builder是() -> ImmutableSet.builder()的簡寫。
- accumulator()返回一個函數(shù),該函數(shù)采用builder和一個T類型的元素。 它只是將上述元素添加到構建器中。
- combiner()返回一個函數(shù),該函數(shù)將接受兩個生成器,并通過將一個中的所有元素添加到另一個中并返回后者來將它們變成一個。 最后finisher()返回一個函數(shù),該函數(shù)會將ImmutableSet.Builder<T>轉換為ImmutableSet<T> 。 同樣,這是以下形式的簡寫語法: builder -> builder.build() 。
- 最后但并非最不重要的一點是, characteristics()告知JDK我們的收集器具有什么功能。 例如,如果ImmutableSet.Builder<T>是線程安全的(不是),我們也可以說Characteristics.CONCURRENT 。
現(xiàn)在,我們可以使用collect()在所有地方使用自定義收集器:
final ImmutableSet<Integer> set = Arrays.asList(1, 2, 3, 4).stream().collect(new ImmutableSetCollector<>());但是創(chuàng)建新實例有點冗長,因此我建議創(chuàng)建靜態(tài)工廠方法,類似于JDK所做的:
public class ImmutableSetCollector<T> implements Collector<T, ImmutableSet.Builder<T>, ImmutableSet<T>> {//...public static <T> Collector<T, ?, ImmutableSet<T>> toImmutableSet() {return new ImmutableSetCollector<>();} }從現(xiàn)在開始,我們只需鍵入以下命令即可充分利用我們的自定義收集器: collect(toImmutableSet()) 。 在第二部分中,我們將學習如何編寫更復雜和有用的收集器。
更新資料
@akarazniewicz 指出收藏家只是折疊的冗長實現(xiàn)。 由于我與褶皺之間的愛與恨關系,我不得不對此發(fā)表評論。 Java 8中的收集器基本上是Scala中最復雜的折疊類型的面向對象封裝,即GenTraversableOnce.aggregate[B](z: ? B)(seqop: (B, A) ? B, combop: (B, B) ? B): B 。 aggregate()就像fold() ,但是需要額外的combop才能將兩個B型累加器組合為一個。 將其與收集器進行比較,參數(shù)z來自seqop() supplier() , seqop()歸約運算是一個accumulator()而combop是一個combop combiner() 。 用偽代碼可以編寫:
finisher(seq.aggregate(collector.supplier())(collector.accumulator(), collector.combiner()))GenTraversableOnce.aggregate()在可能同時進行縮減時使用GenTraversableOnce.aggregate()就像收集器一樣)。
翻譯自: https://www.javacodegeeks.com/2014/07/introduction-to-writing-custom-collectors-in-java-8.html
java 8流自定義收集器
總結
以上是生活随笔為你收集整理的java 8流自定义收集器_Java 8编写自定义收集器简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 家里有八角虫怎么处理 家里有八角虫如何处
- 下一篇: 太的组词 太的组词有哪些