非空のMapに収集/カウントは、ClassCastExceptionがスローされます

jippiee:

私の目標は、地図内のリストの各項目の数を格納することです。これはによって達成することができるgroupingBy()counting()する方法。

私は次の制約は、値を一覧Iでまだ0したがって、すべての可能な値が定義されなければならないことをそのキーのマッピングが必要になるではないということです。

ここで私が作ってみたものです:

Map<String, Long> EMPTY = Map.of("a", 0L,
                                 "b", 0L,
                                 "c", 0L,
                                 "d", 0L);

List<String> list = List.of("a", "a", "d", "c", "d", "c", "a", "d");

Map<String, Long> count = list.stream()
                              .collect(groupingBy(s -> s,
                                                  () -> new HashMap<>(EMPTY),
                                                  counting()));

このコードは、次の例外がスローされます。

Exception in thread "main" java.lang.ClassCastException: class java.lang.Long cannot be cast to class [J (java.lang.Long and [J are in module java.base of loader 'bootstrap')
    at java.base/java.util.stream.Collectors.lambda$groupingBy$53(Collectors.java:1129)
    at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
    at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
    at Test.main(Test.java:18)

しかし、私はちょうど交換する場合new HashMap<>(EMPTY)new HashMap<>()、コードの作品の罰金。

収集プロセスのための空のMapを使用していないことで何かに違反アムI?どのように私はそれ以外のストリームを使用して、私の目標を達成するのでしょうか?

マイケル:

それは奇妙なエラーのビットです。具体的には、(使用のおかげで、使用していることをコレクタはCollectors.counting)実際にプリミティブの単一要素アレイに蓄積されているlongS。

public static <T> Collector<T, ?, Long> summingLong(ToLongFunction<? super T> mapper) 
{
    return new CollectorImpl<>(
        () -> new long[1],
        (a, t) -> { a[0] += mapper.applyAsLong(t); },
        (a, b) -> { a[0] += b[0]; return a; },
        a -> a[0], CH_NOID);
}

場合はgroupingByないcomputeIfAbsent、それは得ることを期待していますlong[]が、あなたはすでに「」のためのキーを持っているので、あなたが戻って取得Longアキュムレータで受け入れの型が一致しないと。それは例外をスローものです。

A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
downstreamAccumulator.accept(container, t);

その後、彼らは置き換えマップ値のすべてを:

intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));

(上記で定義された「フィニッシャー」を使用してa -> a[0]から行くように)long[]に秒Long秒。


はい、それは少しのいたずらだが、あなたは、契約に違反しました

mapFactory:新しい提供するサプライヤー空のMapの結果が挿入されると

それは一種公正十分なのもあります。彼らは取っているHashMapコンパイル時に決定されたがためにMap<String, Long>、彼らは入れているlong[]ことに秒。ので、それは可能ですジェネリックが具体化されていません実行時に、それは単にだHashMapキーと値のいずれかのタイプを格納することができます。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=186751&siteId=1