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
を返す。