T - リダクション操作の入力要素の型A - リダクション操作の可変蓄積の型(通常は実装詳細として隠蔽される)R - リダクション操作の結果の型public interface Collector<T,A,R>
可変リダクション操作の例としては、Collectionへの要素の蓄積、StringBuilderを使用した文字列の連結、要素に関するサマリー情報(合計、最小、最大、平均など)の計算、ピボット・テーブル・サマリー(「販売業者別の最大金額取引」など)の計算、などが挙げられます。クラスCollectorsには、一般的な可変リダクションの実装が多数用意されています。
 
Collectorの仕様を決定する4つの関数は、互いに連携して動作することにより、可変結果コンテナにエントリを蓄積し、オプションでその結果に対して最終的な変換を実行します。これらは次のとおりです。 
supplier())accumulator())combiner())finisher())また、コレクタには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);  // result without splitting
     A a2 = supplier.get();
     accumulator.accept(a2, t1);
     A a3 = supplier.get();
     accumulator.accept(a3, t2);
     R r2 = finisher.apply(combiner.apply(a2, a3));  // result with splitting
  UNORDERED特性を持たないコレクタでは、蓄積された2つの結果a1とa2が等しくなるのは、finisher.apply(a1).equals(finisher.apply(a2))の場合になります。順序付けされていないコレクタでは、等価性の条件が緩和され、順序の違いに関する非等価が許容されるようになります。(たとえば、要素をListに蓄積した順序付けされていないコレクタは、2つのリストが同じ要素を含んでいれば両者を等しいとみなし、順序は無視します。)
 
Stream.collect(Collector)のような、Collectorに基づいてリダクションを実装しているライブラリは、次の制約に従う必要があります。
 
Collectorに追加の同期を実装しなくても収集を並列に行える。リダクション実装は、入力が正しく分割され、各パーティションが隔離状態で処理され、蓄積完了後にのみ結合が実行されるように管理する必要がある。Collector.Characteristics.UNORDERED特性を持つ場合、または元となるデータが順序付けされていない場合だけにすべきである。Collectorsの定義済の実装のほかに、staticファクトリメソッド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)でも実装されています)。Collectorによるリダクション操作の実行時には、次と同等の結果が生成されるべきです。
 
     R container = collector.supplier().get();
     for (T t : data)
         collector.accumulator().accept(container, t);
     return collector.finisher().apply(container);
 ただしライブラリは、入力を自由に分割し、パーティションごとにリダクションを実行した後、コンバイナ関数を使って部分的な結果を結合することにより、並列リダクションを実現することができます。(そのパフォーマンスの善し悪しは、実際のリダクション操作ごとに異なる可能性があります。具体的には、アキュムレータ関数やコンバイナ関数の相対的なコストによって決まります。)
コレクタは合成可能なように設計されています。Collectorsのメソッドの多くは、あるコレクタを受け取って新しいコレクタを生成する関数になっています。たとえば、従業員ストリームの給料の合計を計算する次のようなコレクタがあるとします。
 
     Collector<Employee, ?, Integer> summingSalaries
         = Collectors.summingInt(Employee::getSalary))
 Collectors.groupingBy(Function, Collector)を使えば「給料の合計」のロジックを再利用できます。
 
     Collector<Employee, ?, Map<Department, Integer>> summingSalariesByDept
         = Collectors.groupingBy(Employee::getDepartment, summingSalaries);
 Stream.collect(Collector), Collectors| 修飾子と型 | インタフェースと説明 | 
|---|---|
| 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()新しい可変結果コンテナを作成して返す関数。 | 
BiConsumer<A,T> accumulator()
BinaryOperator<A> combiner()
Function<A,R> finisher()
Aから最終結果の型Rへの最終的な変換を実行します。
 特性IDENTITY_TRANSFORMが設定されている場合、この関数は、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特性を持ちます。T - 新しいコレクタの入力要素の型R - 新しいコレクタの中間蓄積結果と最終結果の型supplier - 新しいコレクタのサプライヤ関数accumulator - 新しいコレクタのアキュムレータ関数combiner - 新しいコレクタのコンバイナ関数characteristics - 新しいコレクタのコレクタ特性CollectorNullPointerException - いずれかの引数がnullの場合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を返します。T - 新しいコレクタの入力要素の型A - 新しいコレクタの中間蓄積の型R - 新しいコレクタの最終結果の型supplier - 新しいコレクタのサプライヤ関数accumulator - 新しいコレクタのアキュムレータ関数combiner - 新しいコレクタのコンバイナ関数finisher - 新しいコレクタのフィニッシャ関数characteristics - 新しいコレクタのコレクタ特性CollectorNullPointerException - いずれかの引数がnullの場合 バグまたは機能を送信 
詳細なAPIリファレンスおよび開発者ドキュメントについては、Java SEのドキュメントを参照してください。そのドキュメントには、概念的な概要、用語の定義、回避方法、有効なコード例などの、開発者を対象にしたより詳細な説明が含まれています。
 Copyright© 1993, 2014, Oracle and/or its affiliates. All rights reserved.