ArrayList 源码解析
作者:前行
- 2023-09-13 广东
本文字数:2217 字
阅读完需:约 7 分钟
核心的属性
默认的初始化容量:private static final int DEFAULT_CAPACITY = 10;
空的数组实例:private static final Object[] EMPTY_ELEMENTDATA = {};
使用默认的容量大小空的数组实例:private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
缓冲数组:transient Object[] elementData;
第一次使用才初始化
ArrayList 的大小:private int size;
构造器
ArrayList 提供了多个构造器
// 无参构造方法,初始容量10
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 初始容量为设定值
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);
}
}
// 通过集合初始化一个ArrayList
// c不能为null,否则报 NPE
public ArrayList(Collection<? extends E> c) {
Object[] a = c.toArray();
if ((size = a.length) != 0) {
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
// replace with empty array.
elementData = EMPTY_ELEMENTDATA;
}
}
复制代码
数组拷贝
// java.util.Arrays
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
//
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
复制代码
存值方法 add()
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
modCount++;
int numNew = a.length;
if (numNew == 0)
return false;
Object[] elementData;
final int s;
if (numNew > (elementData = this.elementData).length - (s = size))
elementData = grow(s + numNew);
System.arraycopy(a, 0, elementData, s, numNew);
size = s + numNew;
return true;
}
复制代码
扩容方法 grow()
private Object[] grow() {
return grow(size + 1);
}
private Object[] grow(int minCapacity) {
// 拷贝元素到新的数组中,底层调用的是 System.arraycopy方法
return elementData = Arrays.copyOf(elementData,
newCapacity(minCapacity));
}
// 计算新的容量: 1.5倍的上一次的容量
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity <= 0) {
// 无参构造器初始化
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
return Math.max(DEFAULT_CAPACITY, minCapacity);
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return minCapacity;
}
return (newCapacity - MAX_ARRAY_SIZE <= 0)
? newCapacity
: hugeCapacity(minCapacity);
}
复制代码
无参构造的扩容
@Test
void debugArrayList() {
List<String> arrayList = new ArrayList<>();
// 第一次扩容 size=10
arrayList.add("1");
for (int i = 2; i <= 10; i++) {
arrayList.add(""+i);
}
// 第二次扩容 size=15
arrayList.add("11");
for (int i = 12; i <= 15; i++) {
arrayList.add(""+i);
}
// 第二次扩容 size=22
arrayList.add("16");
}
复制代码
指定初始容量的扩容
@Test
void debugArrayListWithInitialCap() {
List<String> arrayList = new ArrayList<>(20);
for (int i = 1; i <= 20; i++) {
arrayList.add("" + i);
}
// 第一次扩容, int newCapacity = oldCapacity + (oldCapacity >> 1);
// newCapacity =20+10=30
arrayList.add("21");
for (int i = 22; i <= 30; i++) {
arrayList.add(""+i);
}
// 第二次扩容 size=30+15=45
arrayList.add("31");
}
复制代码
取值方法 get()
public E get(int index) {
Objects.checkIndex(index, size);
return elementData(index);
}
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
复制代码
经典错误
使用完 list 不做 clear
See Also
划线
评论
复制
发布于: 刚刚阅读数: 5
版权声明: 本文为 InfoQ 作者【前行】的原创文章。
原文链接:【http://xie.infoq.cn/article/415689c8da34547a22b307ab8】。文章转载请联系作者。
前行
关注
还未添加个人签名 2018-09-06 加入
还未添加个人简介
评论