查看一些代码,我注意到一个奇怪的ArrayList初始化:
... = new ArrayList<..>(0);
我打开了 JavaSE 7 源,看到内部elementData arrray由空数组常量{}
初始化。当我们将容量传递给ArrayList
构造函数时,我们几乎完全相同 - new Object[0]
。所以我的问题是:新ArrayList(0)
和new ArrayList()
之间有什么区别吗? ArrayList
不应该将默认容量大小设置为像10一样?
谢谢大家的回答。
答案 0 :(得分:7)
有必要澄清两个定义:
尺寸表示列表中元素的数量。
容量表示内部数组的长度。换句话说,长度包含放置元素的位置数;
使用Arraylist的默认构造函数创建一个列表时:
例如:
List<String> list = new ArrayList<>();
System.out.println(l.size());
输出为:0
为什么?
因为列表是空的,所以列表的内部数组解释了这一点,当你使用ArrayList的默认构造函数时,内部数组是:
private static final Object[] EMPTY_ELEMENTDATA = {};
因此,一个空数组的对象,其中长度的值为0(容量)。由于列表为空,大小为0.
向列表中添加一个元素时,列表的大小会增加到1,列表的初始内部数组会被另一个长度为10(容量)的数组更改; (elementData = 30的id)
private static final int DEFAULT_CAPACITY = 10
关于ArrayList的默认构造函数,API java说: API Java:https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#ArrayList%28%29
public ArrayList()
Constructs an empty list with an initial capacity of ten.
换句话说,这个构造函数创建一个空列表(大小等于0),初始容量为10个元素。(在列表中添加一个元素后,列表的容量变为10)
当您知道列表的大小时,您应该使用此大小创建列表。为什么?因为方法add (E element)
的复杂性是O(1)摊销(当列表中有可用空间时),但O(n)(最坏情况)如果添加的元素多于列表的初始容量在这种情况下,分配一个新数组(大小的1.5倍),并将旧数组复制到新数组。显然,这种操作在性能和内存资源方面都有成本。
因此,创建一个初始容量为0的列表是没有意义的。如果您不知道列表的初始容量,请使用默认构造函数,该构造函数为您提供一个初始容量为10个元素的列表。
请记住,ArrayList周围的大小和容量定义是不同的:
From book Core Java 2: Fundamentals
将数组列表分配为新的ArrayList&lt;&#39; Employee&gt;(100)// 容量是100
与新员工[100] //大小为100
分配新数组不同数组列表的容量与数组大小之间存在重要区别。如果您分配一个100的数组 条目,然后阵列有100个插槽,准备使用。数组列表 容量为100的元素有可能持有100个元素 元素(事实上,超过100个元素,代价是额外的元素 重新分配);但在开始时,即使在它的最初之后 构造,数组列表根本不包含任何元素。
答案 1 :(得分:4)
ArrayList
有一个内部数组来存储列表元素。
Java 7和8中的两个构造函数调用之间存在差异:
如果你new ArrayList<>(0)
,ArrayList
会创建一个大小为0的新Object数据。
如果执行new ArrayList<>()
,ArrayList
使用大小为0的静态空Object数组,并在将项添加到列表后切换到自己的私有数组。
编辑:
默认ArrayList
构造函数的Javadoc似乎与此相矛盾。
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
super();
this.elementData = EMPTY_DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // = static, empty
}
但是它不会立即创建长度为10的元素数组,而是在添加元素或确保容量时:
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
? 0
// larger than default for default empty table. It's already
// supposed to be at default size.
: DEFAULT_CAPACITY; // = 10
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
答案 2 :(得分:1)
ArrayList有2个构造函数。默认构造函数只调用capacity = 10的另一个构造函数:
ArrayList() {this(10);}
ArrayList(capacity)
什么能力意味着什么?这意味着分配了一个大小容量的数组来保存arraylist中的项目。只要它太小而无法容纳必要的项目,它就会被调整大小,通过创建一个更大的数组并复制一切(需要时间)+它意味着旧的数组需要被垃圾收集(更多的时间) )。这就是为什么正确的容量是正确的。虽然它可以用于任何初始容量,但它可能很慢。另一方面,拥有巨大的容量,几乎没有任何物品浪费记忆。
注意:Arraylist(0)将创建一个0大小的数组,当您尝试添加第一个元素时,它将被丢弃并分配一个新数组。
答案 3 :(得分:1)
ArrayList()将在添加第一个元素后使列表容量为10(默认值)。但是,ArrayList(0)将保持较小的容量 - 在第一个元素添加后,它将为1,在第二个添加后为2,等等。