关于这个系列,因为开发主要用的是java语言,一直想写写java开发中常用的一些类(虽然这才是开始的第三篇>_<),所有就起了“扒一扒”系列。这个系列会有框架,或者其他学到的东西。文章尽量做到简洁,用少的篇幅理顺相关的知识点和使用方法。废话少说,接下来扒一扒ArrayList这个集合类。
一、数据结构
让我们先看下ArrayList所在包的位置,在java.util.ArrayList中(如图1-1),它在jdk中的util中,说明它在开发中比较常用。从它的名字能看出数据结构为一个数组,看一下这个类的私有属性。
private transient Object[] elementData;//注意transient的意思,以及是否能够进行序列化。
从上面的代码可以印证,它的内部结构为数组。
图1-1
图上为ArrayList的继承关系图
二、常用方法
先说一下,如果要操作list,一定要确保类已经实例化,或者方法参数传进来的不为null,否则会造成NPE异常。可以用collectionutils工具做判空验证。
1、boolean add(E e)
2、get(int index)
3、Iterator<E> iterator()
4、size()
三、源码主要关注点
由于底层的数据结构是数组,被初始化的时候不能更改,当调用add方法的时候会进行判断是否数组容量可用,如果不满足会进行扩容。主要的扩容代码为:
private void ensureCapacityInternal(int minCapacity) {
if (elementData == 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);
}
/**
* 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;
}
主要的逻辑,当调用add方法的时候会判断是否是初始扩容,如果是就进行初始设置,之后每次增加会判断是否需要扩容,每次扩容为原来的1.5倍。
ArrayList是线程不安全的(不懂什么是线程安全可以google下*—*),当多个线程操作时会发生错误。不能循环for遍历的时候边删除,这会抛modexception异常。需要线程安全的list可以去看下,Java .util.concurrent包下的类。
源码中有的方法经常用到System.arrayCoy这个方法,这是一个native方法,属于一个底层方法。
希望这篇文章能够帮到你,如果您感兴趣请看jdk源码。那会增加你的技能点。