- 成员变量
/**
* 默认初始化大小,如果不指定,则底层存储结构默认为一个长度为10个存储单位的数组
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 空数组,用户传入为0,则使用此数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 默认数组,当使用无参构造时使用此数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 存储该ArrayList数据对象的数组
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* 该ArrayList数组中实际元素的个数
*/
private int size;
- 构造方法
/**
* 有参构造,参数为非负整数
* 根据传入的整型数字,来构造一个对应大小的数组
*/
public ArrayList(int initialCapacity) {
//step1.如果传入初始化容量大于0,则创建一个对应大小的数组
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
//step2.如果传入初始化容量等于0,则使用默认为空的数组
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
//step3.其他情况皆异常
} else {
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
/**
* 无参构造方法,创建一个默认的长度为10的空数组
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 根据集合来进行构造ArrayList
*/
public ArrayList(Collection<? extends E> c) {
//step1.集合转为数组
elementData = c.toArray();
//step2.如果此数组长度不等于0,拷贝为一个object数组
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);
//step3.其他情况都使用空数组
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
- 添加元素(动态扩容机制)
/**
* 向ArrayList添加一个元素
*/
public boolean add(E e) {
//step1.确定容量,扩容
ensureCapacityInternal(size + 1);
//step2.添加元素
elementData[size++] = e;
//step3.添加成功
return true;
}
/**
* 扩容
*/
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
/**
* 获取最小扩容
* 添加第一个元素前底层数组容量为0
* 添加第一个元素后底层数组容量成为了10
*/
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
/**
* 根据所需最小扩容量来判断是否需要扩容
*/
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
//minCapacity为数组中实际元素的个数,而不是数组长度
//当第1次添加元素的时候,此时minCapacity=1 elementData.length=0,经过calculateCapacity(Object[] elementData, int minCapacity),返回为10,此时入参minCapacity=10,扩容一次
//当第2次添加元素时候,此时minCapacity=2,elementData.length=10,经过calculateCapacity(Object[] elementData, int minCapacity),返回为2,此时入参minCapacity=2,不会扩容
//当第3,4,...,10次添加元素时,minCapacity - elementData.length > 0 不成立,不会扩容
//直到第11次,minCapacity - elementData.length > 0 成立,再次扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* ArrayList真实扩容方法
**/
private void grow(int minCapacity) {
// step1.计算原始容量
int oldCapacity = elementData.length;
//step2.计算新容量以1.5倍来扩容,采用位运算,右移1位位原来数字的0.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
//step3.如果新容量小于最小所需容量,则使用最小容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//step4.如果新容量大于ArrayList分配的容量大小,则计算最小容量与ArrayList最大容量的大小
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//step5.拷贝新List
elementData = Arrays.copyOf(elementData, newCapacity);
}
/***
**计算最小容量与ArrayList最大容量的大小
***/
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
ArrayList扩容中用到了位移运算
int newCapacity = oldCapacity + (oldCapacity >> 1);
包括HashMap中的哈希寻址算法,计算哈希值右移16位,将高低16进行异或运算,大大提高了运算效率
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
HashMap添加元素计算哈希地址时也取模运算
(n - 1) & hash
也采用了逻辑操作
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}