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

Posted

技术标签:

【中文标题】为啥 Arrays.asList() 返回自己的 ArrayList 实现【英文标题】:Why does Arrays.asList() return its own ArrayList implementation为什么 Arrays.asList() 返回自己的 ArrayList 实现 【发布时间】:2011-06-07 05:30:30 【问题描述】:

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

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

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

您还可以通过java.util.Arrays.ArrayList 实现获得什么?

【问题讨论】:

【参考方案1】:

你问:

还有什么你会从 java.util.Arrays.ArrayList 实施?

这是因为 Arrays.asList 返回的 Arrays$ArrayList 只是对原始数组的一个视图。所以当原始数组改变时,视图也会改变。

如果使用真正的 ArrayList,则元素将被复制,并且对原始数组的更改不会影响 ArrayList。

这样做的原因很简单:

性能:无需复制任何东西 内存高效:不需要第二个数组

【讨论】:

正确,但原因除外。文档意味着只有数据直写是数组和集合基础 API 之间的桥梁 @sblundy 和文档不仅意味着新娘“此方法还提供了一种方便的方法来创建初始化为包含多个元素的固定大小的 ist”。但我给你一票。 这是我使用它的卑鄙原因。 我喜欢“视图”的解释。 @Ralph 谢谢。我很早就弄错了。 view.set(0, 42) 也将更改 original[0]。 Arrays.ArraysList 包含对原始数组的private final E[] a 引用【参考方案2】:

javadoc 说asList 返回“由指定数组支持的固定大小的列表”。如果要调整数组大小,则必须创建一个新数组并复制旧数据。比列表不会由相同的数组实例支持。既定目标是“此方法充当基于数组的 API 和基于集合的 API 之间的桥梁”。因此,对底层数组的直写是一项设计要求。

【讨论】:

【参考方案3】:

它们是具有不同行为的两个不同类。

当您调用Arrays.asList 时返回的列表是对数组的薄包装,而不是副本。返回的列表是固定大小的:尝试调用add 将引发UnsupportedOperationException 异常。

另一方面,java.util.ArrayList 保留自己的内部数据副本,并且大小可变。

【讨论】:

【参考方案4】:

Arrays.asList 需要返回一个无法调整大小的列表——因为基础数组无法调整大小——但这是可修改的——因为允许分配给基础数组中的元素。

【讨论】:

【参考方案5】:

实际上,您可以使用 add 将元素添加到 ArrayList。这样的方法:

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

在我看来,您使用它来获取 List 的功能,但将它们应用于 Array 。

【讨论】:

不,您不能将元素添加到从 Arrays.asList(T ... a) 返回的 java.utils.Arrays.ArrayList 中。您的代码 sn-p 构造了一个新的 java.util.ArrayList,就像您展示的那样,它支持#add。【参考方案6】:

两个cmets:

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

因此,一旦返回 List,您可以在数组或返回的 List 中过度存储现有元素,但不允许扩大数组或缩小数组。

    响应:

    实际上,您可以使用 add 将元素添加到 ArrayList。像这样的方法: 列表 l2=新的 ArrayList(Arrays.asList(array1)); l2.add("blueCheese");

l2 是列表的独立副本,因此 List l2 现在与原始数组&List 解耦。所以 blueCheese 在 l2 中,但不在彼此备份的原始数组/列表中。

-dbednar

【讨论】:

以上是关于为啥 Arrays.asList() 返回自己的 ArrayList 实现的主要内容,如果未能解决你的问题,请参考以下文章

为啥直接将 Arrays.asList() 分配给 var 时会出现 AssertionError?

Java Arrays.asList

Arrays.asList( ) 返回一个特殊的“ArrayList”

Arrays.asList 小结

关于Arrays.asList()返回的ArrayList

Arrays.asList():返回指定数组支持的固定大小列表