首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >收集/计数非空映射抛出ClassCastException

收集/计数非空映射抛出ClassCastException
EN

Stack Overflow用户
提问于 2019-01-29 16:54:50
回答 3查看 460关注 0票数 4

我的目标是在Map中存储列表中每一项的计数。这可以通过groupingBy()counting()方法来实现。

我所拥有的下一个约束是,对于列表中没有的值,我仍然需要将该键映射为0。因此,必须定义所有可能的值。

以下是我想出的:

代码语言:javascript
运行
复制
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()));

此代码引发以下异常:

代码语言:javascript
运行
复制
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而违反了什么?否则,我如何使用流来实现我的目标呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-01-29 17:18:44

这是个奇怪的错误。具体来说,您使用的收集器(借助Collectors.counting)实际上正在积累到原始long的单个元素数组中。

代码语言:javascript
运行
复制
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[],但是因为您已经有了一个"a“的键,所以返回一个Long,它与累加器所接受的类型不匹配。这就是抛出异常的原因。

代码语言:javascript
运行
复制
A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
downstreamAccumulator.accept(container, t);

稍后,它们将替换所有的映射值:

代码语言:javascript
运行
复制
intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));

使用上面定义的“finisher”(a -> a[0])从long[]s转到Longs。

是的,有点淘气,但你违反了合同

mapFactory:提供新的空映射的供应商,将结果插入其中

所以这也很公平。他们正在使用一个在编译时被确定为Map<String, Long>Map<String, Long>,并将long[]投入其中。这是可能的,因为仿制药没有被具体化。在运行时,它只是一个能够存储任何类型的键和值的HashMap

票数 3
EN

Stack Overflow用户

发布于 2019-01-29 17:18:22

正如文档为Collectors.groupingBy​(classifier, mapFactory, downstream)声明的那样

参数:

  • 分类器--将输入元素映射到键的分类器函数
  • 下游--实现下游还原的收集器
  • mapFactory -提供新的空地图的供应商,结果将被插入*
票数 2
EN

Stack Overflow用户

发布于 2019-01-29 17:36:19

流列表,并使用groupingBycounting将其转换为Map<String,Long>,然后在EMPTY映射中使用foreach更新值。

代码语言:javascript
运行
复制
list.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()))
    .forEach((k,v)->empty.put(k, v));   //java coding standards variable name should be in lower case 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54426000

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档