While I was doing some programming, I came across a ClassCastException . As a background, I give a simplified version of the exercise to demonstrate the problem:
For a string containing only characters A or B , output a map with characters in the form of keys and the number of occurrences as values. In addition, the card must always contain both characters as a key (with a value of 0 if the character is not in the input string).
Examples:
"A" => {A=1, B=0}"AAB" => {A=2, B=1}
My first solution was the following:
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; }
This solution worked, but I wanted to try if I could provide a map with the default values โโof the groupingBy function:
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; }
When calling createResult2 with input A a ClassCastException is ClassCastException at runtime:
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)
Can someone explain why this is happening?