ArrayList的对象创建时的默认内存分配

时间:2014-05-28 16:39:13

标签: java memory-management collections arraylist

假设我们正在创建 ArrayList 对象,如

ArrayList<User> list=new ArrayList<User>();
System.out.println(list.size());   // it will be 0 at this time

现在我的问题是,当在堆中创建此列表对象时,将分配什么内存。我想知道如果列表的大小动态增长,在运行时如何分配这个内存大小。

3 个答案:

答案 0 :(得分:4)

ArrayList<User> list=new ArrayList<User>();

将创建一个空的ArrayList。此时没有创建用户的任何对象或将其添加到ArrayList,并且在您明确添加到用户之前永远不会。

此时

size()将返回0,因为ArrayList中没有元素。

ArrayList的大小为capacityArrayList由数组支持。容量是一定数量的数组。

  

每个ArrayList个实例都有一个capacity。容量是大小   用于存储列表中元素的数组。它总是在   至少与列表大小一样大。随着元素被添加到   ArrayList,其容量自动增长。增长的细节   除了添加元素之外,没有指定策略   持续摊销的时间成本。

当通过default constructor创建ArrayList时,会创建一个容量为10的ArrayList。

从技术上讲,列表占用的实际内存将基于容量。但请注意,数组/列表为空。因此,容量的增加只会对占用的总体规模产生微小影响。

您可以使用Java VisualVM(JDK附带)等工具来检查对象占用的大小。

答案 1 :(得分:1)

第1部分:创建列表对象时分配的内存:

创建没有默认大小的ArrayList时,将调用以下构造函数:

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    super();
    this.elementData = EMPTY_ELEMENTDATA;
}

super()这里调用一个什么都不做的AbstractList构造函数。 this.elementData设置为空数组对象。因此,分配的内存将是ArrayList类的不同属性的大小之和+分配给类本身的16个字节:

public class ArrayList<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;

/**
 * Default initial capacity.
 */
private static final int DEFAULT_CAPACITY = 10;

/**
 * Shared empty array instance used for empty instances.
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer. Any
 * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
 * DEFAULT_CAPACITY when the first element is added.
 */
transient Object[] elementData; // non-private to simplify nested class access

/**
 * The size of the ArrayList (the number of elements it contains).
 *
 * @serial
 */
private int size;

 ....

您可以查看default sizes of primitive data types并进行数学计算,以了解所使用的确切内存。

但是,由于初始化了一个空elementData数组,所以没有内存用于存储任何数据。

第2部分:如果列表大小动态增长,则在运行时如何分配此内存大小。

首先,我们看到ArrayList使用数组elementData来保存对象。有一种方法已经摊销了恒定的时间,我不能完全记住它的名字。

但是想法是当ArrayList类使用的数组被填充时,数组的大小加倍。当删除ArrayList元素并且只填充了1/4的数组时,数组的大小减半。

答案 2 :(得分:1)

要回答问题的第二部分,是的,当您向ArrayList添加元素时,分配的内存会动态增长。您可以通过查看源代码来估计空ArrayList的大小。 ArrayList本身只声明了三个字段:

private static final long serialVersionUID = 8683452581122892189L;
private transient Object[] elementData;
private int size;

对于空列表,将在64位jvm中消耗20个字节。 ArrayList扩展了AbstractList(包括其私有类)声明:

int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
protected transient int modCount = 0;
private int offset;
private int size;
private int expectedModCount;

增加了28个字节,总共48个字节。