public interface Collector<T,A,R>
可変的簡約処理には、要素のCollectionへの累積・文字列のStringBuilderを使った連結・要素に関する和や最小値や最大値や平均などの要約情報の計算・「販売者ごとの最も売り上げが大きい取引」などの「ピボットテーブル」の計算などを含む。Collectorsクラスには多くの一般的な可変的簡約の実装が用意されている。
Collectorは要素を結果コンテナに協調して累積し、追加可能な処理として結果に対して最終的な変換をする4つの関数によって記述される。その4つの関数とは次の通りである。
supplier())accumulator())combiner())finisher())CollectorはCollector.Characteristics.CONCURRENTといった特性の集合を備える。これらの特性は簡約の実装がより良い性能を出すためのヒントとして扱われる。
コレクタを使った簡約の逐次的な実装は供給関数を使って1つの結果コンテナのみを生成し、各入力要素に対して1回ずつ累積関数を呼びだすだろう。並列実装は入力を分割し、各部分ごとに結果コンテナを作成し、各部分の要素を中間結果に対して累積し、統合関数を使って中間結果を併合して統合結果を得るだろう。
逐次的な実行と並列実行が等価な結果を作成するよう保障するためには、集約関数は単位元と結合性に関する制約を満たす必要がある。
単位元の制約では中間累積結果に対して空の結果コンテナを統合しても等価な結果が生成されることが定められている。つまり、いくつかの累積と統合の結果である中間累積結果aに対して、aはcombiner.apply(a, supplier.get())と等価である必要がある。
結合性の制約では計算を分割しても等価な結果が生成さえることが定められている。つまり、任意の入力t1とt2に対し、下記の計算における結果r1とr2は等価である必要がある。
A a1 = supplier.get();
accumulator.accept(a1, t1);
accumulator.accept(a1, t2);
R r1 = finisher.apply(a1); // 分割しない場合の結果
A a2 = supplier.get();
accumulator.accept(a2, t1);
A a3 = supplier.get();
accumulator.accept(a3, t2);
R r2 = finisher.apply(combiner.apply(a2, a3)); // 分割した場合の結果
UNORDERED特性を持たないコレクタに関しては、累積結果a1とa2はfinisher.apply(a1).equals(finisher.apply(a2))が成り立つときに等価である。順序を持たないコレクタに関しては、等価性は順序の違いによる差異を許すように緩めることもある(例えば、要素をListに累積する、順序を持たないコレクタは、2つのリストが順序を無視して同じ要素を含んでいれば等価であるとして扱うだろう)。
Stream.collect(Collector)のように、Collectorに基いて簡約を実装するライブラリは次の制約を遵守する必要がある。
Collectorが余分な同期処理を実装しなくても収集を並列に実行できるようになる。簡約の実装は、入力が重なりを持たずに分割され、分割処理は他の処理から分離して進行され、統合処理は累積処理が完了した後にのみ起きるようにやりくりする必要がある。Collector.Characteristics.UNORDERED特性を持つか、元のデータが順序を持たないときにのみ適用されるべきである。コレクタの構築には、Collectorsに予め用意された実装に加え、静的ファクトリメソッドof(Supplier, BiConsumer, BinaryOperator, Characteristics...)も利用できる。例えば、ウィジェットをTreeSetに累積するコレクタを次のように作成できる。
Collector<Widget, ?, TreeSet<Widget>> intoSet =
Collector.of(TreeSet::new, TreeSet::add,
(left, right) -> { left.addAll(right); return left; });
この挙動は予め用意されたコレクタCollectors.toCollection(Supplier)を使っても実装できる。
| 修飾子とタイプ | インタフェースと説明 |
|---|---|
static class |
Collector.Characteristics
簡約処理の実装の最適化に利用できる、
Collectorの性質を表す特性。 |
| 修飾子とタイプ | メソッドと説明 |
|---|---|
BiConsumer<A,T> |
accumulator()
値を可変な結果コンテナに折り畳む関数。
|
Set<Collector.Characteristics> |
characteristics()
このCollectorの特性を示す
Collector.CharacteristicsのSetを返す。 |
BinaryOperator<A> |
combiner()
部分的な結果を2つ取ってそれらを併合する関数。
|
Function<A,R> |
finisher()
中間累積型
Aから最終結果型Rへの最終変換を実行する。 |
static <T,A,R> Collector<T,A,R> |
of(Supplier<A> supplier,
BiConsumer<A,T> accumulator,
BinaryOperator<A> combiner,
Function<A,R> finisher,
Collector.Characteristics... characteristics)
与えられた
supplier, accumulator, combiner, finisherによって表わされる新しいCollectorを返す。 |
static <T,R> Collector<T,R,R> |
of(Supplier<R> supplier,
BiConsumer<R,T> accumulator,
BinaryOperator<R> combiner,
Collector.Characteristics... characteristics)
与えられた関数
supplier, accumulator, combinerによって表わされる新しいCollectorを返す。 |
Supplier<A> |
supplier()
新しい可変な結果コンテナを作成して返す関数。
|
Supplier<A> supplier()
BinaryOperator<A> combiner()
Function<A,R> finisher()
Aから最終結果型Rへの最終変換を実行する。 もしIDENTITY_FINISH特性がセットされている場合、この関数はAからRへの非チェックキャストを伴なう恒等変換と仮定してもよい。
Set<Collector.Characteristics> characteristics()
Collector.CharacteristicsのSetを返す。この集合は不変であるべきである。
static <T,R> Collector<T,R,R> of(Supplier<R> supplier, BiConsumer<R,T> accumulator, BinaryOperator<R> combiner, Collector.Characteristics... characteristics)
supplier, accumulator, combinerによって表わされる新しいCollectorを返す。結果となるCollectorはCollector.Characteristics.IDENTITY_FINISH特性を備える。
static <T,A,R> Collector<T,A,R> of(Supplier<A> supplier, BiConsumer<A,T> accumulator, BinaryOperator<A> combiner, Function<A,R> finisher, Collector.Characteristics... characteristics)
supplier, accumulator, combiner, finisherによって表わされる新しいCollectorを返す。