Java8 - 如何将List<List<String>>添加到List<List<String>>?

4

我有两个List<List<String>>,想要将它们拼接在一起。

这是我的代码:

List<List<String>> a = Arrays.asList(Arrays.asList("a", "b", "c"));
List<List<String>> b = Arrays.asList(Arrays.asList("d", "e", "f"));
a.addAll(b);

但是它无法运行并抛出异常。

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:148)
    at java.util.AbstractList.add(AbstractList.java:108)
    at java.util.AbstractCollection.addAll(AbstractCollection.java:344)

以下代码有效:
List<List<String>> a = new ArrayList<>();
a.add(Arrays.asList("a", "b", "c"));
List<List<String>> b = new ArrayList<>();
b.add(Arrays.asList("d", "e", "f"));
a.addAll(b);

这里有什么区别?


3
请更新你的问题,附上一个完整可运行的程序,以说明你的问题。 - tgdavies
https://dev59.com/o3VC5IYBdhLWcg3wxEJ1 - Ravi Makwana
1
如果 a.addAll(b) 不起作用,那么你肯定做错了什么。请编辑并分享你正在执行的代码。 - azro
3
Arrays.asList会创建一个固定大小的列表,详见文档。如果下一个问题中"不工作"可以更具体一些(它是如何不工作的),但"抛出错误"并不足够,至少要提及异常,最好还包括其堆栈跟踪信息! - user16320675
"有什么区别 " --> Arrays.asList() =!= new ArrayList<>() - 第一个是 方法,第二个是 构造函数 - 第一个返回一个 Listjava.util.Arrays$ArrayList 的实例,是 Arrays 的嵌套类),第二个创建了一个 java.util.ArrayList 的实例(尽管与第一个具有相同的名称 [不幸地],但它们是不同的类)。 - user16320675
显示剩余2条评论
3个回答

8
你使用 a.addAll(b) 的尝试只有在 外部列表 a 是可变的且你不介意修改它的情况下才能成功。

可变的外部列表:

List<List<String>> a = new ArrayList<>(List.of(
        List.of("a", "b", "c"),
        List.of("d", "e", "f")));

List<List<String>> b = new ArrayList<>(List.of(
        List.of("h", "i", "j"),
        List.of("k", "l", "m")));

a.addAll(b); // the 'a' will contain all the inner lists

a.forEach(System.out::println);

不可变的外部列表

如果您想保留原先的ab列表和/或生成一个新列表,请使用

List<List<String>> a = List.of(
        List.of("a", "b", "c"),
        List.of("d", "e", "f"));

List<List<String>> b = List.of(
        List.of("h", "i", "j"),
        List.of("k", "l", "m"));

List<List<String>> result = Stream.of(a, b)
        .flatMap(Collection::stream)
        .collect(Collectors.toList());

result.forEach(System.out::println);

结果

两种方式具有相同的输出:

[a, b, c]
[d, e, f]
[h, i, j]
[k, l, m]
无论内部列表是否为不可变的,在这种组合中都没有关系。

1
最后一段代码的替代方案Stream.concat(a.stream(), b.stream()).toList()(较新版本的Java);或者 Stream.concat(a.stream(), b.stream()).collect(Collectors.toList())(Java 16之前 [我想])。 - user16320675
concat 似乎是更好的选择。干得好! - Nikolas Charalambidis

2
您的代码无法正常工作,因为Arrays.asList()返回的是由指定数组支持的固定大小列表。 https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#asList(T...) 这意味着当您尝试添加更多元素时,表示List的数组中没有空间;从而抛出UnsupportedOperationException
如果您想要构建具有特定元素并且能够扩展其大小的List,则应使用该类的转换构造函数,通过向其提供由asList()方法返回的列表来实现。
List<List<String>> a = new ArrayList<>(Arrays.asList(new ArrayList<>(Arrays.asList("a", "b", "c"))));
List<List<String>> b = new ArrayList<>(Arrays.asList(new ArrayList<>(Arrays.asList("d", "e", "f"))));
a.addAll(b);

这样,你的外部和内部列表都将表现为实际的List,而不会在超过原始大小时抛出UnsupportedOperationException


-2
您可以避免使用addAll函数,而是像下面所示迭代b并将其添加到a中:
for(innerList:b){
   a.add(innerList);
}

1
同样的问题,我怀疑... - user16320675

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接