java - 为什么我不能在参数中使用通配符类型来计算

标签 java generics lambda

直奔主题(我知道应该避免使用 wildcard types as the returning type )
我在写这个 answer以及以下代码:

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;
}
得到以下警告:
Required type: capture of ?

Provided: capture of ?
以及 IntelliJ 的建议

Change variable 'map' to 'Map<?, Object'


这更没有意义。当然,当我尝试应用该建议时它失败了。
最初,我虽然“好吧,这与它与计算签名不匹配的事实有关”,即:
default V compute(K key, ...) 
所以我试过了
public class MyMap <T>{
    public static <T> void nothing(Collection<T> c){
         // Empty
    }
}
 public static Map<?, Long> manualMap(Collection<Collection<?>> c, Map<?, Long> map){
     c.forEach(MyMap::nothing);
     return map;
 }
我没有问题。
以下两个版本:
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;
}
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;
}
工作没有任何问题(除了(T)情况下的警告)。
所以问题是
为什么第一个版本不起作用?

最佳答案

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;
}
在这里,您有三个通配符:一个用于参数,一个用于映射变量,一个用于返回值。 (返回值一不是 super 相关)。
您正在尝试将元素从集合(一种通配符类型)传递到映射方法(另一种通配符类型)中。
编译器不知道这两个“意味着”相同,因此它不接受需要“ map ”通配符的“集合”通配符。
您可以通过类型变量指示它们是相同的类型:
public static <T> Map<?, Long> manualMap(Collection<T> c){
    Map<T, Long> map = new HashMap<>();
    c.forEach(e -> map.compute(e, (k, v) -> (v == null) ? 1 : v + 1));
    return map;
}
这里,T 是一个你不知道的类型;但你知道在这两种情况下它都是相同的未知类型。
或者您可以以不需要两个通配符的方式声明它:
return c.stream().collect(groupingBy(a -> a, counting()));

关于java - 为什么我不能在参数中使用通配符类型来计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66322345/

相关文章:

java - 具有两个流的 Lambda

java - 手写扫描文档到 .txt 文件?

java - 为什么所有的接口(interface)方法都需要在java实现它的类中实现

c# - 在运行时调用通用接口(interface)方法的有效方法

c# - 求值表达式 通用 C# 求值条件 多态性

c++ - 为什么不对这些函数签名进行相同的处理?

java - 如何在新文本区域设置光标?

java - 对这个简单的多态性例子感到困惑

Java模板函数

python - 舍入 lambda 函数