Going straight to the point (I know that one should avoid using wildcard types as the returning type)
I was writing this answer and the following code:
public static Map<?, Long> manualMap(Collection<?> c){
Map<?, Long> map = new HashMap<>();
c.forEach(e -> map.compute(e, (k, v) -> (v == null) ? 1 : v + 1));
return map;
}
which gets the following warning:
Required type: capture of ?
Provided: capture of ?
and a suggestion from IntelliJ to
Change variable 'map' to 'Map<?, Object'
which makes even less sense. Naturally, it fails when I try to apply the suggestion.
Originally, I though "okey it has to do with the fact that it does not match the compute signature", namely:
default V compute(K key, ...)
So I tried
public class MyMap <T>{
public static <T> void nothing(Collection<T> c){
// Empty
}
}
and
public static Map<?, Long> manualMap(Collection<Collection<?>> c, Map<?, Long> map){
c.forEach(MyMap::nothing);
return map;
}
and I had no issue.
The following two versions:
public static <T> Map<?, Long> manualMap(Collection<?> c){
Map<T, Long> map = new HashMap<>();
c.forEach(e -> map.compute((T) e, (k, v) -> (v == null) ? 1 : v + 1));
return map;
}
and
public static Map<?, Long> manualMap(Collection<?> c){
Map<Object, Long> map = new HashMap<>();
c.forEach(e -> map.compute(e, (k, v) -> (v == null) ? 1 : v + 1));
return map;
}
work without any problem (except for a warning in the (T) the case).
So the question is
Why the first version does not work?