关于这个系列,因为开发主要用的是java语言,一直想写写java开发中常用的一些类(虽然这才是开始的第三篇>_<),所有就起了“扒一扒”系列。这个系列会有框架,或者其他学到的东西。文章尽量做到简洁,用少的篇幅理顺相关的知识点和使用方法。废话少说,接下来扒一扒ArrayList这个集合类。

一、数据结构

让我们先看下ArrayList所在包的位置,在java.util.ArrayList中(如图1-1),它在jdk中的util中,说明它在开发中比较常用。从它的名字能看出数据结构为一个数组,看一下这个类的私有属性。



private transient Object[] elementData;//注意transient的意思,以及是否能够进行序列化。



 从上面的代码可以印证,它的内部结构为数组。 

java 分类信息网源码 javalibrary分类贴吧_java 分类信息网源码

 

图1-1

java 分类信息网源码 javalibrary分类贴吧_java_02

图上为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源码。那会增加你的技能点。