私の目標は、地図内のリストの各項目の数を格納することです。これはによって達成することができる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
)実際にプリミティブの単一要素アレイに蓄積されているlong
S。
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
キーと値のいずれかのタイプを格納することができます。