Multimaps中的Java Generics擦除

pet*_*ust 4 java generics guava

我有两个MultimapString通过(i)索引小号IntegerS和(ⅱ)DoubleS和一个例程到的输出列出String秒.

public static void outputInteger(Multimap<Integer, String> map) {
    for (Integer key : map.keySet()) {
        Collection<String> strings = map.get(key);
        output(strings);
    }
}

public static void outputDouble(Multimap<Double, String> map) {
    for (Double key : map.keySet()) {
        Collection<String> strings = map.get(key);
        output(strings);
    }
}
Run Code Online (Sandbox Code Playgroud)

我想用这些组合成一个单一的程序Number为一体的超IntegerDouble

public static void outputNumber(Multimap<? extends Number, String> map) {
    for (Number key : map.keySet()) {
        Collection<String> ids = map.get(key); //** 
    }
}
Run Code Online (Sandbox Code Playgroud)

但是星号线不能编译

The method get(capture#5-of ? extends Number) in the type 
Multimap<capture#5-of ? extends Number,String> is not 
applicable for the arguments (Number)
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?

Mar*_*ers 9

声明

Multimap<? extends Number, String> map;
Run Code Online (Sandbox Code Playgroud)

表示该映射的密钥类型是未知但具体的子类型(包括).换句话说,编译器认为它可能是一个Multimap<Integer, String>,或者Multimap<Short, String>,或者Multimap<Number, String>,等基于这个原因,你不能打电话map.get(Number),因为据编译器知道,它可能是一个Multimap<Double, String>.

无法做到这一点的原因更为明显put.如果你能够做到put(Number, String)map?不,因为如果它碰巧是a Multimap<Integer, String>,那么你可以添加一个Double密钥,然后它会违反地图的完整性.

使用普通Map<K, V>接口,这不是get定义的问题get(Object),不是get(K).

保罗的答案对这种情况有很好的解决方法.本质上,他使用一个中间泛型方法给出capture#5-of ? extends Number一个名称(类型参数T)的未知类型(在本例中表示).这允许您关联在两个不同上下文中发生的捕获,以便您可以跨这些上下文执行某些操作.


Pau*_*ora 7

您应该能够使用通用方法来实现您想要的:

public static <T extends Number> void outputNumber(Multimap<T, String> map) {
    for (T key : map.keySet()) {
        Collection<String> strings = map.get(key);
        output(strings);
    }
}
Run Code Online (Sandbox Code Playgroud)

它不与通配符工作的原因是因为? extends Number意味着一些未知类型是或扩展Number.同时,Number key可以引用其他一些不兼容的类型(对于所有编译器都知道).

  • @ peter.murray.rust:事实上,路易斯的答案是解决这个特定问题的一个很好的解决方案(它更正确,更有效),而保罗的方法解决了更一般的情况(基于你的代码更像是一个稻草人的假设) . (2认同)
  • @ peter.murray.rust:如果你需要键和值的集合,路易斯的方法仍然很好,只需迭代`entrySet()`而不是`values()`. (2认同)

Lou*_*man 7

public static void output(Multimap<? extends Number, String> map) {
    for (Collection<String> strings : map.asMap().values()) {
        output(strings);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 甚至可以只是`Multimap <?,String>`给出在那里做的事情. (2认同)