コレクターをカスタマイズする方法

コレクタークラスのJava 1.8は、既存のインタフェースは、需要を満たすことができないならば、それはコレクターをカスタマイズする方法である必要があり、コンビニエンスインタフェースの多くを提供しますか?


  メソッドは呼び出すことで可能のコレクタは、デフォルトの実装を提供します。

    public static<T, A, R> Collector<T, A, R> of(Supplier<A> supplier,
                                                 BiConsumer<A, T> accumulator,
                                                 BinaryOperator<A> combiner,
                                                 Function<A, R> finisher,
                                                 Characteristics... characteristics) {
        ...
        Set<Characteristics> cs = Collectors.CH_NOID;
        if (characteristics.length > 0) {
            cs = EnumSet.noneOf(Characteristics.class);
            Collections.addAll(cs, characteristics);
            cs = Collections.unmodifiableSet(cs);
        }
        return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, finisher, cs);
    }
  • サプライヤは蓄積のために、オブジェクトの入力パラメータを提供します。
  • アキュムレータは蓄積動作を提供します。
  • 入力された複数のオブジェクトを合成する合成、通常のシリアル(シーケンシャル)の唯一の入力オブジェクトの場合は、同時動作が蒸気(平行)オブジェクトを使用する場合時に合わせなければならない、無視することができます。
  • 我々が必要とするタイプに最終結果を計算するためのフィニッシャー手段と、
  • 指定されたタイプの動作を最適化するための特性;

  入力パラメータに述べたタイプコメント変数タイプが(可変)が提供されなければならないことに留意されたいです。

@param <A> the mutable accumulation type of the reduction operation (often hidden as an implementation detail)

  見てみましょうコレクタークラスのソースコードは、例えば、一般的なToListメソッドメソッドへのコレクタ・インタフェースを実現する方法であります

static final Set<Collector.Characteristics> CH_ID = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));

public static <T> Collector<T, ?, List<T>> toList() {
    return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, 
                               List::add,
                               (left, right) -> { 
                                    left.addAll(right); 
                                    return left; 
                               },
                               CH_ID);
}

  ToListメソッドの方法では、サプライヤーのArrayList ::新しいように、二つのリストをリスト::コンバイナのリストと呼ばれるアキュムレータに追加の累算操作が達成されるのaddAllマージを使用して、ArrayListのを蓄積するための容器を提供し
、最終的なタイプがリストであるため、したがってToListメソッドはフィニッシャ無視し、最適化IDENTITY_FINISHタイプを使用して直接フィニッシャ演算結果を返す必要がない示します。


  クラスリストの合計数の統計的要件は、需要があると仮定すると、

 public class A {
    
    private int count;

    public A(int count) {
        this.count = count;
    }

    public int getCount() {
        return count;
    }
}

  ここでの方法は、単にsummingIntコレクターmapToIntを使用するか、クラスによって提供することができます。

var aList = new ArrayList<A>();
...
int totalUseMap = aList.stream().mapToInt(A::getCount).sum();
// or
int totalUseCollect = aList.stream().collect(Collectors.summingInt(Obj::getCount));

  カスタムコレクターズ言葉を使用する場合、どのようにそれを達成するには?

var aList = new ArrayList<A>();
...
int total = aList.parallelStream().collect(Collector.of(() -> new int[1],
                                                (result, a) -> result[0] += a.getCount(),
                                                (a, b) -> {
                                                    a[0] += b[0];
                                                    return a;
                                                },
                                                result -> result[0],
                                                Collector.Characteristics.CONCURRENT));

  サプライヤーは、可変オブジェクトを提供する必要があり、単にそこに提供()することができない- > 0、及び結果はint型を提供するように、INTデフォルトの入力パラメータが矛盾[]型である、セットフィニッシャは、INT結果を型に変換されなければならない
アキュムレータためこれは、同時操作をサポートし、パフォーマンスを向上させる特性を設定するので、同時実行には影響しません。

おすすめ

転載: www.cnblogs.com/yeyu456/p/11989802.html