如何将addAll与泛型集合一起使用?

时间:2013-08-30 08:38:08

标签: java

为什么

List<Map<String, Object>> a, b;
a.addAll(b);

编译

但是

List<? extends Map<String, ?>> a, b;
a.addAll(b);

没有。

如何让后者编译?

6 个答案:

答案 0 :(得分:2)

您无法将项添加到通配符通用列表中。第一个编译因为它有一个已定义的类型。

然而,您可能会找到一些适合您目的的超类,并将其用作通用参数。

<强>更新

另见Wildcard (in the Oracle docs)

答案 1 :(得分:2)

想象一下CustomHashMap扩展HashMap并初始化a如下:

List<CustomHashMap<String, String> list = new ArrayList<CustomHashMap<String, String>>();
List<? extends Map<String, ?>> a = list;

如果您能够将条目添加到a ...

a.add(new HashMap<String, String>());

......你会遇到这种奇怪的情况

CustomHashMap<String, String> map = list.get(0); // you would expect to get CustomHashMap object but you will get a HashMap object instead

换句话说,你不知道Map的实际类型(当你说?extends Map)时,你知道的一切是它是Map的某个子类型,你不能将任意对象添加到List中,因为您需要确保添加的对象有一个超类型。但你不能,因为地图的确切类型是未知的。

答案 2 :(得分:1)

根据java docs你可以在这种情况下声明帮助方法(丑陋但有效):

static <T extends List<K>, V, K extends Map<String, V>> void addAllHelper(T from, T to) {
        from.addAll(to);
}

答案 3 :(得分:0)

当您使用具体的Generic Type声明它时,它会编译。如果您定义一个类:

public class AClass<T extends Map<String, ?>> {

    public List<T> dostuff() {

        List<T> lista = new ArrayList<T>();
        List<T> listb = new ArrayList<T>();

        lista.addAll(listb);
        return lista;
    }
}

使用通配符无法编译。

答案 4 :(得分:0)

您可以使用以下方法执行此操作:

private <S extends Map<String, ?>> void method(List<S> a, List<S> b){
    a.addAll(b);
}

答案 5 :(得分:0)

下面的代码可以帮助您解释这个

List<? super Number> a称为out参数,可用于更新 List<? extends Number> b被称为in参数,可用于阅读

以下注释行导致编译错误,原因如评论

中所述
public static void main(String[] args) {
    List<Integer> intList = new ArrayList<>();
    List<Double> doubleList = new ArrayList<>();
    List<Number> numberList = new ArrayList<>();
    addAll(numberList, intList);
    addAll(numberList, doubleList);
    addAll(intList, doubleList);//cant add double to int
    addAll(doubleList,intList);//cant add int double
    addAll(intList, numberList);//cant add number to int
}

private static<T> void addAll(List<? super T> a, List<? extends T> b) {
    a.addAll(b);
}