java - List<List<String>> 是 Collection<Collection<T>> 的实例吗?

标签 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;
}

然后我试着调用它:

    List<List<String>> resultLists = ... ;
    Set<String> labelsSet = CollectionsHelper.makeSet(resultLists);

我收到以下错误:

<T>makeSet(java.util.Collection<java.util.Collection<T>>) in CollectionsHelper 
cannot be applied to (java.util.List<java.util.List<java.lang.String>>)

现在 List 是一个 CollectionString 是一个 T。那么为什么这行不通,我该如何解决呢?

最佳答案

您的签名应该是:

public static <T> Set<T> makeSet(Collection<? extends Collection<T>> coll);

基本上List<S> 不是 List<T> 的子类型只是因为ST 的子类型.该属性称为 covariance 并且在 Java 中,泛型类型不是协变的(其他语言,例如 scala 包含协变泛型类型)。

你所做的没有用,因为应该可以添加任何 Collection<T>进入Collection<Collection<T>> ,例如,使用您的签名,这将是一个有效的实现:

public static <T> Set<T> makeSet(Collection<Collection<T>> coll) {
    coll.add(new HashSet<T>());
    return null;
}

然后调用这个方法如下:

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

那么这会导致同样的问题吗?不!原因是编译器不允许您将任何内容添加到以未知类型参数化的集合中:

public static <T> Set<T> makeSet(Collection<? extends Collection<T>> coll) {
    coll.add(new HashSet<T>()); //this line will not compile
    return null;
}

拥有通配符首先是必要的,这样你就可以做你想做的事情,这可能是 Collection.addAll 的最好证明。方法被泛型化,因此 List<Number>.addAll(List<Integer>)将被允许​​:

boolean addAll(Collection<? extends T> coll)

关于java - List<List<String>> 是 Collection<Collection<T>> 的实例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1772192/

相关文章:

java - 通用方法协方差 - 有效限制或编译器监督?

c# - Winforms IoC 容器 - 如何使用 Presenter 工厂处理具体类型

java - 转换 java 反射方法调用的返回值

java - 无法从按钮访问 JProgressbar [Java]

java - 为 Talend 设置 Java 环境变量

C#:非泛型类型中的泛型成员?

hibernate - 我怎样才能使带有 IN 的命名查询真正起作用?

java - containsKey HashMap<> 的实现 - Java

java - java中的替换方法

java - java/scala 中的原始对象大小和 'as<SomePrimitive>Buffer() 方法调用