java集合类源码解析(2)---ArrayList

时间:2022-03-15 14:23:04
本章介绍一种工作中及其常用的集合类ArrayList,ArrayList继承AbstractList实现了List&Collection接口的实现,是一种以数组为基础的数据结构,下面我们就具体分析一下ArrayList类中的属性与方法。

类变量&常量

private static final int DEFAULT_CAPACITY = 10;

private static final Object[] EMPTY_ELEMENTDATA = {};

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

transient Object[] elementData;

private int size;

DEFAULT_CAPACITY :初始默认容量10
elementData:list数据,因为transient关键字故不参与序列化
size:数组大小

构造器

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);
}
}

public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTD ATA;
}

public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
this.elementData = EMPTY_ELEMENTDATA;
}
}

一些比较重要的方法

public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}

这个方法是将数组压缩,减少没必要的空间占用避免数组扩展以后浪费空间

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);
}

这几个方法是在add之前需要做的判断,判断数组容量是否足够,如果不够进行扩容(grow)操作

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);
}

这个就是扩容的方法了,新的数组容量是旧的数组容量的1.5倍,如果容量不足以装下数组需要容纳的最小元素数,则取最小元素数为数组新容量,当然也不能超过最大容量


为了数组的操作方便,ArrayList类内部增加了两个匿名类 Itr & ListItr
Itr主要实现了hasNext,next,remove等方法
ListItr 继承了Itr的同时额外实现了hasPrevious,nextIndex,previousIndex,previous,set,add等方法
增强了对数组的操作,看上去好像这数组就是个链表一样。。。= =

ArrayList并没有太多的知识点,在ArrayList使用最多的当属Arrays.copyOf 和System.arraycopy 两个方法,那么 这俩熊孩子有啥区别呢?

Q&A Arrays.copyOf VS System.arraycopy ?

如果看一下源码的话 就会发现,日?Arrays.copyOf不就用的System.arraycopy么?的确。
Array.copyOf与arraycopy的主要不同在于
copyOf将U类型数组转换为T类型数组,而且在内部new一个数组再调用arraycopy
arraycopy则是单纯的将两个object类型指针所指空间进行复制,没有其他保护性校验,异常大大的啊

嗯 以上基本上就是ArrayList的源码解析了,对于在Collection类中的一些方法,本文没有放出,日后再说吧~

to be continued