CopiesList.addAll方法抛出UnsupportedOperationException异常。

3
List<String> hi = Collections.nCopies(10, "Hi");
List<String> are = Collections.nCopies(10, "Are");

hi.addAll(are);

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

输出

Exception in thread "main" java.lang.UnsupportedOperationException
  at java.util.AbstractList.add(Unknown Source)
  at java.util.AbstractList.add(Unknown Source)
  at java.util.AbstractCollection.addAll(Unknown Source)
  at com.practice.java8.lambdaexp.Test.main(Test.java:14)

我认为JDK中没有实现AbstractList.add()方法,所以它不能工作。
但是,如果我使用CopiesList对象创建一个新的ArrayList对象,它会工作,因为它将有适当的add()实现。
我的问题是:为什么CopiesList没有适当的addAll()实现?
2个回答

6

Collections.nCopies返回一个不可变的List,因此您无法向其中添加任何内容:

返回由指定对象的n个副本组成的不可变列表。

它返回一个不可变的List,因为它只包含您传递给其构造函数的元素的单个引用:

新分配的数据对象很小(它只包含对数据对象的单个引用)。

这样做是为了提高性能和存储要求 - Collections.nCopies(10, "Hi")Collections.nCopies(10000000, "Hi")占用相同的空间。

因此,将其实现为可变列表将非常困难。如果没有为该元素分配存储空间,那么如何将第10000个元素设置为一些新值?

如果您需要一个包含相同对象副本的可变列表,则必须将不可变列表传递给某些可变列表构造函数:

List<String> mutable = new ArrayList<>(Collections.nCopies(10, "Hi"));

4
根据 JavaDoc 的描述,返回的列表是不可变的,这意味着您无法修改它:

[nCopies] 返回一个由指定对象的 n 个副本组成的不可变列表。

也许您没有明白 "与 List.addAll 结合使用" 部分。您必须有一个非不可变列表,在其中可以添加所有元素:
List modifiableList = new ArrayList<String>();

List<String> hi = Collections.nCopies(10, "Hi");
List<String> are = Collections.nCopies(10, "Are");

modifiableList.addAll(are);
modifiableList.addAll(hi);

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

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