banner
RustyNail

RustyNail

coder. 【blog】https://rustynail.me 【nostr】wss://ts.relays.world/ wss://relays.world/nostr

定制されたコレクターCollector-GroupingByの実装

タイプの確定#

カスタムコレクタを実装するには、まずタイプを確定する必要があります。

  • 収集する要素のタイプ
  • アキュムレータ /accumulate のタイプ
  • 最終結果のタイプ

次のようなコレクタを実装すると仮定します。

public class GroupingBy<T,K> implements Collector<T,Map<K,List<T>>,Map<K,List<T>>>

それぞれのタイプは次のとおりです。

  • T
  • Map<K,List>
  • Map<K,List>

コレクタのコンポーネントの実装#

コレクタには 4 つの重要なコンポーネントがあります。これらはすべて関数です。

  • supplier
  • accumulator
  • combiner
  • finisher

supplier#

supplier はコンテナを作成するために使用されます。

@Override
    public Supplier<Map<K, List<T>>> supplier() {
        return ()-> new HashMap<>();
    }

accumulator はアキュムレータであり、前の結果に次の内容を追加するために reduce の第 2 引数として使用されます。

 @Override
    public BiConsumer<Map<K, List<T>>, T> accumulator() {
        return (accumulator,ele)->{
            K key = this.classifier.apply(ele);
            List<T> tList = accumulator.get(key);
            if (tList == null){
                tList = new ArrayList<>();
            }
            tList.add(ele);
            accumulator.put(key,tList);
        };
    }

次の要素を追加する前に、マップにリストがあるかどうかを確認します。

重要なポイントは、キーの取得です。渡された classifier によって行われ、classifier を使用してキーを取得します。

combiner#

reduce の第 3 引数に相当し、生成されたコンテナを結合します。

@Override
    public BinaryOperator<Map<K, List<T>>> combiner() {
        return (l,r)->{
            l.putAll(r);
            return l;
        };
    }

後のコンテナを前のコンテナに直接結合して返します。

finisher#

最終結果を記述します。

@Override
    public Function<Map<K, List<T>>, Map<K, List<T>>> finisher() {
        return accumulator->accumulator;
    }

追加の characteristics#

データの返り値の形式を記述します。

@Override
    public Set<Characteristics> characteristics() {
        return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
    }

関連説明:

    /**
     * Characteristics indicating properties of a {@code Collector}, which can
     * be used to optimize reduction implementations.
     */
    enum Characteristics {
        /**
         * Indicates that this collector is <em>concurrent</em>, meaning that
         * the result container can support the accumulator function being
         * called concurrently with the same result container from multiple
         * threads.
         *
         * <p>If a {@code CONCURRENT} collector is not also {@code UNORDERED},
         * then it should only be evaluated concurrently if applied to an
         * unordered data source.
         */
        CONCURRENT,

        /**
         * Indicates that the collection operation does not commit to preserving
         * the encounter order of input elements.  (This might be true if the
         * result container has no intrinsic order, such as a {@link Set}.)
         */
        UNORDERED,

        /**
         * Indicates that the finisher function is the identity function and
         * can be elided.  If set, it must be the case that an unchecked cast
         * from A to R will succeed.
         */
        IDENTITY_FINISH
    }

テスト#

image

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。