假设我们正在创建 ArrayList 对象,如
ArrayList<User> list=new ArrayList<User>();
System.out.println(list.size()); // it will be 0 at this time
现在我的问题是,当在堆中创建此列表对象时,将分配什么内存。我想知道如果列表的大小动态增长,在运行时如何分配这个内存大小。
答案 0 :(得分:4)
ArrayList<User> list=new ArrayList<User>();
将创建一个空的ArrayList
。此时没有创建用户的任何对象或将其添加到ArrayList
,并且在您明确添加到用户之前永远不会。
size()
将返回0
,因为ArrayList
中没有元素。
ArrayList的大小为capacity。 ArrayList
由数组支持。容量是一定数量的数组。
每个
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个字节。