ArrayList的默认大小

时间:2016-02-08 11:26:45

标签: java arrays arraylist

查看一些代码,我注意到一个奇怪的ArrayList初始化:

... = new ArrayList<..>(0);

我打开了 JavaSE 7 源,看到内部elementData arrray由空数组常量{}初始化。当我们将容量传递给ArrayList构造函数时,我们几乎完全相同 - new Object[0]。所以我的问题是:新ArrayList(0)new ArrayList()之间有什么区别吗? ArrayList不应该将默认容量大小设置为像10一样?

谢谢大家的回答。

4 个答案:

答案 0 :(得分:7)

有必要澄清两个定义:

尺寸表示列表中元素的数量。

容量表示内部数组的长度。换句话说,长度包含放置元素的位置数;

Exemple of the length of an array 列表尺寸= 2

使用Arraylist的默认构造函数创建一个列表时:

例如:

List<String> list = new ArrayList<>();
System.out.println(l.size());

输出为:0

为什么?

因为列表是空的,所以列表的内部数组解释了这一点,当你使用ArrayList的默认构造函数时,内部数组是:

private static final Object[] EMPTY_ELEMENTDATA = {}; 

因此,一个空数组的对象,其中长度的值为0(容量)。由于列表为空,大小为0.

state of the list when the default constructor is used (elementData = 27的id)

向列表中添加一个元素时,列表的大小会增加到1,列表的初始内部数组会被另一个长度为10(容量)的数组更改; (elementData = 30的id)

private static final int DEFAULT_CAPACITY = 10

State of the list after add one element  (elementData = 30的id)

关于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,等等。