I'm trying to count occurrences of integers in an array using Collectors.groupingBy
from Java 8 API but I'm getting some strange compilation errors.
Here is my code:
List<Integer> l = Arrays.asList(1, 1, 1, 2, 3, 3, 3, 3);
Map<Integer, Integer> x = l.stream().collect(groupingBy(i -> i, counting()));
Sadly, this won't compile, resulting in the following error:
error: incompatible types: inferred type does not conform to equality constraint(s)
Map<Integer, Integer> x = l.stream().collect(groupingBy(i -> i, counting()));
^
inferred: Integer
equality constraints(s): Integer,Long
1 error
It seems to be a generic type issue, because when I remove the generic Map type, it compiles. Here is another test:
List<Integer> l = Arrays.asList(1, 1, 1, 2, 3, 3, 3, 3);
Map x = l.stream().collect(groupingBy(i -> i, counting()));
System.out.println(x);
And the output is right as expected:
{1=3, 2=1, 3=4}
Any ideas of how to solve that without the need of casting all the types here and there?
If you do:
Map<Integer, Long> x = l.stream().collect(Collectors.groupingBy(i -> i, Collectors.counting()));
then your code will compile just fine.
The reason is that the Collectors.counting()
method is defined as:
public static <T> Collector<T, ?, Long> counting()
Here, the third type-parameter denotes the type which will be used in the BinaryOperator
that is used for calculating the count.
Note that when you remove the type-parameter for the Map
:
Map x = l.stream().collect(groupingBy(i -> i, counting()));
then the statement successfully compiles, because you're actually working with the raw version of Map
, i.e. the type for both keys and values will be Object
(which is compatible with Long
, Integer
and friends). However, using raw types is something that should be avoided, as you can get annoying ClassCastException
(s) at Runtime.
counting()
is declared as:
static <T> Collector<T,?,Long>
... whereas you're trying to use it as if it produces an Integer
.
If you change your code to:
Map<Integer, Long> x = l.stream().collect(groupingBy(i -> i, counting()));
... it will compile with no problems. Note that in your current code using the raw type, your output actually has Long
values rather than Integer
values... it's just you can't tell that from the string representation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With