为什么Arrays.asList()返回自己的ArrayList实现

47

我最近发现Java中实际上有两种不同的ArrayList实现(迟到总比不到好吧...)。

那么,我想知道为什么Arrays.asList(T... a)需要返回一个不可调整大小的列表?如果他们需要一个不可修改的列表,为什么还要添加set(int index, E element)方法呢?

所以我的一般问题是,为什么Arrays.asList(T... a)方法不返回java.util.ArrayList?

此外,java.util.Arrays.ArrayList实现能带来什么好处?

6个回答

60
您的问题是:

还有,使用 java.util.Arrays.ArrayList 实现有什么好处吗?

这是因为 Arrays.asList 返回的 Arrays$ArrayList 只是对原始数组的一种视图。所以当原始数组发生变化时,视图也会发生变化。
如果使用真正的 ArrayList,则元素将被复制,对原始数组的更改将不会影响 ArrayList。
这样做的原因很简单:
  • 性能好:无需复制任何内容
  • 内存高效:不需要第二个数组

1
真实的,除了原因之外。文档仅提到数据写入缓存作为数组和集合基础API之间的桥梁。 - sblundy
@sblundy和文档都提到了,这个方法不仅可以创建一个包含多个元素的固定大小的列表,而且还提供了一种方便的方式。但我会给你点赞。 - Ralph
这就是我使用它的主要原因。 - sblundy
我喜欢“视图”解释。 - zwh
@Yossarian42:不,它的行为就像一个视图:看看我的小测试: @Test public void testView() { Integer[] original = new Integer[] {1}; List<Integer> view = Arrays.asList(original); original[0] = 2; assertThat(view).containsExactly(2);} - Ralph
1
@Ralph 谢谢。我早先理解错了。view.set(0, 42)也会改变original[0]。Arrays.ArraysList包含对原始数组的private final E[] a引用。 - Yossarian42

13

javadoc文档显示asList返回“由指定数组支持的固定大小列表”。如果你想要改变这个数组的大小,你必须创建一个新的数组并且复制旧数据。那么这个列表就不会再由同一个数组实例支持。该方法的目标是“在基于数组和基于集合的API之间提供桥梁”,因此向底层数组的写入是设计要求。


7
他们是两个具有不同行为的类。
当您调用 Arrays.asList 时返回的列表是数组的薄包装,而不是副本。返回的列表是固定大小的:尝试调用add将抛出UnsupportedOperationException异常。
另一方面,java.util.ArrayList 会保留其自己的内部数据副本,并且可以变化大小。

6
Arrays.asList需要返回一个不能被调整大小的列表,因为底层数组不能被调整大小,但可以修改,因为允许对底层数组中的元素进行赋值。

3

实际上,您可以使用add方法向ArrayList添加元素,就像这样:

List<String> l2= new ArrayList<String>(Arrays.asList(array1));
l2.add("blueCheese");

在我看来,你可以使用它(指 Array)获取 List 的特性并应用于数组中。


4
不,你无法向从Arrays.asList(T... a)返回的java.utils.Arrays.ArrayList添加元素。你的代码片段构造了一个新的java.util.ArrayList,就像你展示的那样,支持#add操作。 - David Groomes

1

两个注释:

1、试图通过调用List接口的remove()方法来缩小返回的数组将抛出UnsupportedOperationException。这是因为Arrays类内部的ArrayList类扩展了AbstractList,并且AbstractList中的remove()方法会抛出UnsupportedException。

因此,一旦返回List,您可以在数组中或返回的List中覆盖现有元素,但不允许增加或缩小数组。

  1. 回复:

实际上,您可以使用add.方法向ArrayList添加元素,如下所示: List l2= new ArrayList(Arrays.asList(array1)); l2.add("blueCheese");

l2是列表的独立副本,因此List l2现在与原始数组&List分离。 因此,l2中有蓝色奶酪,但原始数组/List没有。

-dbednar


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