Mar*_*zon 8 java generics collections covariance
我编写了这个方便的通用函数,用于将集合集合转换为单个集合:
public static <T> Set<T> makeSet(Collection<Collection<T>> a_collection) {
Iterator<Collection<T>> it = a_collection.iterator();
Set<T> result = new HashSet<T>();
while (it.hasNext()) {
result.addAll(it.next());
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
然后我试着打电话给它:
List<List<String>> resultLists = ... ;
Set<String> labelsSet = CollectionsHelper.makeSet(resultLists);
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
<T>makeSet(java.util.Collection<java.util.Collection<T>>) in CollectionsHelper
cannot be applied to (java.util.List<java.util.List<java.lang.String>>)
Run Code Online (Sandbox Code Playgroud)
现在a List
是a Collection
,a String
是a T
.那么为什么这不起作用,我该如何解决呢?
你的签名应该是:
public static <T> Set<T> makeSet(Collection<? extends Collection<T>> coll);
Run Code Online (Sandbox Code Playgroud)
基本上List<S>
是不是一个亚型的List<T>
,只是因为S
是的一个亚型T
.该属性称为协方差,在Java中,泛型类型不是协变的(其他语言如scala包含协变泛型类型).
你做了什么没有用,因为它应该可以添加任何Collection<T>
一个Collection<Collection<T>>
,所以例如,你的签名,这将是一个有效的实现:
public static <T> Set<T> makeSet(Collection<Collection<T>> coll) {
coll.add(new HashSet<T>());
return null;
}
Run Code Online (Sandbox Code Playgroud)
但是后来调用这个方法如下:
List<List<String>> outside = new LinkedList<List<String>>();
makeSet(outside); //actually this line will not compile!
List<String> oops = outside.get(0); //oh dear - it's a HashSet
Run Code Online (Sandbox Code Playgroud)
那么这会导致同样的问题吗?没有!原因是编译器不允许您在未知类型参数化的集合中添加任何内容:
public static <T> Set<T> makeSet(Collection<? extends Collection<T>> coll) {
coll.add(new HashSet<T>()); //this line will not compile
return null;
}
Run Code Online (Sandbox Code Playgroud)
首先需要使用通配符,以便您可以执行类似于您想要执行的操作,可能最好地通过该Collection.addAll
方法的生成方式进行说明,以便List<Number>.addAll(List<Integer>)
允许:
boolean addAll(Collection<? extends T> coll)
Run Code Online (Sandbox Code Playgroud)
public static <T> Set<T> makeSet(Collection<? extends Collection<T>> a_collection) {
Iterator<? extends Collection<T>> it = a_collection.iterator();
Set<T> result = new HashSet<T>();
while (it.hasNext()) {
result.addAll(it.next());
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2149 次 |
最近记录: |