ArrayList
常量说明
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
通过以上可以看出ArrayList
默认容量值为 10, 默认元素数据为 {}
只有在增加第一个元素的时候,默认容量才会被分配。
这也是减少内存开销的一种方式,我们在日常代码开发中也可加以灵活运用。
元素存储
/**
* 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 == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access
ArrayList
中元素存储在 elementData
数组对象中。且该数组对象是 transient
的
对象实例化
无参构造
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
案例:
@Test
public void testNoArgCon() {
// 使用无参构造创建对象,此时,
// this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
// 即 this.elementData = {}
List<String> list = new ArrayList<>();
// Any empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
// will be expanded to DEFAULT_CAPACITY when the first element is added.
// 即 先 this.elementData = new Object[10];
// 此时 ArrayList 容量为 10 ;
list.add("空列表,增加第一个元素时,分配默认容量");
}
## 指定容量实例化
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
## 将其他集合转换实例化
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
# 存储优化
/**
* Trims the capacity of this <tt>ArrayList</tt> instance to be the
* list's current size. An application can use this operation to minimize
* the storage of an <tt>ArrayList</tt> instance.
*/
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
> 案例:
@Test
public void testTrimToSize() {
// 使用无参构造创建对象,此时,
// this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
// 即 this.elementData = {}
ArrayList<String> list = new ArrayList<>();
// Any empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
// will be expanded to DEFAULT_CAPACITY when the first element is added.
// 即 先 this.elementData = new Object[10];
// 此时 ArrayList 容量为 10 ;
list.add("空列表,增加第一个元素时,分配默认容量");
// 通过该方法整理空间
// 整理后 ArrayList 容量为 1 ;
// 相较于整理前 节省了 9个 容量。起到了优化作用
list.trimToSize();
}
# 扩容
/**
* Increases the capacity of this <tt>ArrayList</tt> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
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;
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容一半
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
> 关于扩容过程最好带入几种情况,去跟踪一下,会更加形象地理解整个过程。
> 具体跟踪过程略,感兴趣的同学自己操作下。
---
了解更多 [java基础:目录索引](https://blog.51cto.com/u_14889520/4838367)