在分组中使用自定义地图供应商时出现ClassCastException

eee*_*eee 7 java java-8 java-stream

当我做一些编程练习时,我偶然发现了一个ClassCastException.作为背景我正在提供演示的简化版本来演示问题:

给定一个只包含字符的字符串,A或者B计算一个以字符为键的映射,并将出现的次数作为值.此外,地图应始终包含两个字符作为键(如果输入字符串中缺少字符,则值为零).

例子:

  • "A" => {A=1, B=0}
  • "AAB" => {A=2, B=1}

我的第一个解决方案如下:

import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;

public Map<Character, Long> createResult(String input) {
    Map<Character, Long> map = input.chars()
        .mapToObj(c -> (char) c)
        .collect(groupingBy(c -> c, counting()));

    map.putIfAbsent('A', 0L);
    map.putIfAbsent('B', 0L);
    return map;
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案有效,但我想尝试是否可以为groupingBy函数提供默认值的地图:

public HashMap<Character, Long> createResult2(String input) {
    return input.chars()
        .mapToObj(c -> (char) c)
        .collect(groupingBy(c -> c, this::mapFactory, counting()));
}

private HashMap<Character, Long> mapFactory() {
    HashMap<Character, Long> map = new HashMap<>();
    map.put('A', 0L);
    map.put('B', 0L);
    return map;
}
Run Code Online (Sandbox Code Playgroud)

createResult2使用输入调用时,会在运行时抛出Aa ClassCastException:

java.lang.ClassCastException: java.lang.Long cannot be cast to [Ljava.lang.Object;
    at java.util.stream.Collectors.lambda$groupingBy$45(Collectors.java:909)
    at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
    at java.util.stream.IntPipeline$4$1.accept(IntPipeline.java:250)
    at java.lang.CharSequence$1CharIterator.forEachRemaining(CharSequence.java:149)
    at java.util.Spliterators$IntIteratorSpliterator.forEachRemaining(Spliterators.java:1908)
    at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

任何人都可以解释为什么会这样吗?

小智 0

为什么不是一个简单的循环呢?

private static Map<Character, Integer> count(String input) {
    Map<Character, Integer> result = new HashMap<>();
    result.put('A', 0);
    result.put('B', 0);
    for (Character c : input.toCharArray()) {
        result.put(c, result.get(c) + 1);
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

  • @talex:只需将“result.put(c, result.get(c) + 1);”替换为“result.merge(c, 1, Integer::sum);”,问题就解决了。如果不使用零预先初始化映射,而是执行 `map.putIfAbsent('A', 0L); ,那么效率会更高。map.putIfAbsent('B', 0L);` 之后,就像问题中一样。 (4认同)