常用集合类
1. ArrayList 源码分析
ArrayList内部使用的是一个数组来保存数据. 主要是利用
Arrays.copyOf()
方法来动态扩展数组长度. ArrayList还是相对简单的.
1.1 ArrayList原理
ArrayList内部使用了一个 Object[]
来存储数据。
// 存储数据的数组
private transient Object[] elementData;
ArrayList初始化时可以指定数组大小
// 指定数组大小,初始化ArrayList.
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
如果不指定大小则, 默认是空数组
// 默认空数组定义
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 无参数构造方法
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
1.2 ArrayList 优化函数.
当不在添加元素时, 将剩余的空间释放掉.
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
1.3 增加元素API
默认情况下元素添加到最后一个元素的后面
public boolean add(E e) {
// 设置数组长度, 确保数组够长.如果不够会自动增加长度.
ensureCapacityInternal(size + 1); // Increments modCount!!
// size是当前元素个数. 下面这句代码是将元素添加到最后.
elementData[size++] = e;
return true;
}
下面来看下 ensureCapacityInternal
更新数组实际长度的方法.
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// 判断当前数组长度是否小于数组长度. 如果不小于则增加长度.
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
下面来看下 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);
}
上面的代码非常简单首先将数组长度增加2倍, 如果还是不够长度, 则直接将长度增加到minCapacity.之后还要比较此时长度是否超过最大长度.处理过程如下
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
在指定位置添加元素API
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
// 将要插入位置以后的元素, 整体后移.
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
// 在index位置插入.
elementData[index] = element;
size++;
}
1.4 删除元素API
remove(index)
public E remove(int index) {
rangeCheck(index);
modCount++;
// 获取要删除元素值.
E oldValue = elementData(index);
// 获取要删除元素的个数.
int numMoved = size - index - 1;
// 将index 之后的元素前移
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 将最后一个位置设置为null
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
ArrayList的结构相对简单.也容易理解.