I have a List of data objects which I need to group in various ways, then perform common operations on the grouped results. So I am trying to extract the common operations to a single method, as in the following contrived example:
private static void print(List<Integer> data,
Collector<Integer, ?, Map<?, List<Integer>>> collector) {
data.stream().collect(collector)
.forEach((key, list) -> System.out.println(key + ": " + list));
}
private static void printByMagnitude() {
List<Integer> data = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
print(data, Collectors.<Integer,String>groupingBy(i -> i < 5 ? "small" : "large"));
}
private static void printByModulus() {
List<Integer> data = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
print(data, Collectors.<Integer,Integer>groupingBy(i -> i % 2));
}
Note that in the print
method, the collector's result type is a Map
with unknown keys, Map<?, List<Integer>>
, since when I print by magnitude I use String
keys, and when I print by modulus I use Integer
keys.
This code gives two compilation errors, on both calls to Collectors.groupingBy
. The first complains about the call with String
keys:
Error:(19, 58) java: incompatible types:
java.util.stream.Collector<java.lang.Integer,capture#1 of ?,
java.util.Map<java.lang.String,java.util.List<java.lang.Integer>>>
cannot be converted to
java.util.stream.Collector<java.lang.Integer,?,
java.util.Map<?,java.util.List<java.lang.Integer>>>
The second complains about the call with Integer
keys:
Error:(24, 59) java: incompatible types:
java.util.stream.Collector<java.lang.Integer,capture#2 of ?,
java.util.Map<java.lang.Integer,java.util.List<java.lang.Integer>>>
cannot be converted to
java.util.stream.Collector<java.lang.Integer,?,
java.util.Map<?,java.util.List<java.lang.Integer>>>
The return type of Collectors.groupingBy
is <T, K> Collector<T, ?, Map<K, List<T>>>
, so in the Magnitude
and Modulus
cases this should be
Collector<Integer, ?, Map<String,List<Integer>>>
Collector<Integer, ?, Map<Integer,List<Integer>>>
respectively.
Why don't these match the collector parameter in print
,
Collector<Integer, ?, Map<?, List<Integer>>> collector
?