我遇到了java中泛型的问题,尤其是通配符。我有一个Map
(outerMap
),其值是另一个Map
(innerMap
)元素,其值为List
元素。嵌套通配符编译失败调用方法
请参阅下面的java类,我已创建该类来演示此行为。不包括进口报表。忽略使用方法里面流,那是无关紧要的:
public class SSCCE {
public static void main(String[] args) {
// Setup
List<Double> doubles = Arrays.asList(1.0,2.0,3.0);
Map<Integer, List<Double>> innerMap = new HashMap<>();
innerMap.put(1, doubles);
Map<String, Map<Integer, List<Double>>> outerMap = new HashMap<>();
outerMap.put("hello", innerMap);
// Test
// This method call works fine.
Stream<Integer> streamFromInner = getStreamOfMappingToN(innerMap);
// This method call does not work - causes below compilation error.
Stream<Integer> stream = getStreamOfMergedDistinctMappingToN(outerMap);
}
private static <T, U> Stream<T> getStreamOfMappingToN(Map<T, ? extends Collection<U>> map) {
return map.entrySet().stream().map(q -> q.getKey());
}
private static <T, U> Stream<T> getStreamOfMergedDistinctMappingToN(Map<String, Map<T, ? extends Collection<U>>> map) {
return map.entrySet().stream().flatMap(
p -> getStreamOfMappingToN(p.getValue())
).distinct();
}
}
我看到下面的编译错误,在第二个方法调用:
method getStreamOfMergedDistinctMappingToN in class SSCCE cannot be applied to given types;
required: Map<String,Map<T,? extends Collection<U>>>
found: Map<String,Map<Integer,List<Double>>>
reason: cannot infer type-variable(s) T,U
(argument mismatch; Map<String,Map<Integer,List<Double>>> cannot be converted to Map<String,Map<T,? extends Collection<U>>>)
where T,U are type-variables:
T extends Object declared in method <T,U>getStreamOfMergedDistinctMappingToN(Map<String,Map<T,? extends Collection<U>>>)
U extends Object declared in method <T,U>getStreamOfMergedDistinctMappingToN(Map<String,Map<T,? extends Collection<U>>>)
任何人可以说明为什么发生这种情况与第二方法调用,而不是第一个?两个方法签名均包含Map<T, ? extends Collection<U>>
,但只有第二个方法无法与呼叫相匹配。如果我用List<U>
替换有问题的? extends Collection<U>
,它可以正常工作,因为我实际上将它传递给List
,但这看起来很懒惰,并不能解释为什么我看到此错误。
我已经在这方面做了一些阅读,有些人有类似的问题,并解释了他们的问题 - 许多人认为通配符的级别很重要 - 但没有理解这里发生了什么,我很难将其他解决方案与这个问题联系起来。它仍然很混乱。通过阅读,我发现如果我在第二个方法声明中将Map<T, ? extends Collection<U>>
替换为? extends Map<T, ? extends Collection<U>>
,它编译得很好,但我不明白为什么,以及为什么第一个方法签名可以工作。
我希望你对此反馈意见。
这个代码更实际的问题(即使你编译它),是很难弄清楚发生了什么。 – biziclop
@biziclop当然,这不是我的实际代码,它只是表现了问题。基于'Collection'中的内容,我正在使用流从'Entry'映射到'T',但是我留下了很多内容,因为我不认为它与问题相关。T和U也是一样,它们可以是任何东西。 –
http://bayou.io/draft/Capturing_Wildcards.html#Nested_Wildcards – ZhongYu