Java集合框架源码解读(1)——ArrayList、LinkedList和Vector

java.util.List接口是Java Collections Framework的一个重要组成部分,List接口的架构图如下:

Java集合框架源码解读(1)——ArrayList、LinkedList和Vector_第1张图片

本文将通过剖析List接口的三个实现类——ArrayListLinkedListVector的源码,带你走近List的世界。

ArrayList

ArrayList是List接口可调整数组大小的实现。实现所有可选列表操作,并允许放入包括空值在内的所有元素。每个ArrayList都有一个容量(capacity,区别于size),表示底层数组的实际大小,容器内存储元素的个数不能多于当前容量。

底层实现

java.util.ArrayList类的继承关系如下:

public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable

其中需要注意的是RandomAccess接口,这是一个标记接口,没有定义任何具体的内容,该接口的意义是随机存取数据。在该接口的注释中有这样一段话:

/** for (int i=0, n=list.size(); i < n; i++) { list.get(i); } runs faster than this loop: for (Iterator i=list.iterator(); i.hasNext(); ) { i.next(); } **/

这说明在数据量很大的情况下,采用迭代器遍历实现了该接口的集合,速度比较慢。

实现了RandomAccess接口的集合有:ArrayList, AttributeList, CopyOnWriteArrayList, RoleList, RoleUnresolvedList, StackVector等。

ArrayList一些重要的字段如下:

    private static final int DEFAULT_CAPACITY = 10;
    private static final Object[] EMPTY_ELEMENTDATA = {};
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    transient Object[] elementData; // non-private to simplify nested class access
    private int size;//底层数组中实际元素个数,区别于capacity

可以看到,默认第一次插入元素时创建数组的大小为10。当向容器中添加元素时,如果容量不足,容器会自动增加50%的容量。增加容量的函数grow()源码如下:

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);//右移一位代表增加50%
        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;
    }

值得注意的是,由于集合框架用到了编译器提供的语法糖——泛型,而Java泛型的内在实现是通过类型擦除和类型强制转换来进行的,其实存储的数据类型都是Raw Type,因此集合框架的底层数组都是Object数组,可以容纳任何对象。

数组复制

ArrayList的实现中大量地调用了Arrays.copyof()System.arraycopy()方法。在此介绍一下这两个方法。

System.arraycopy()方法是一个native方法,调用了系统的C/C++代码,在openJDK中可以看到其源码。该方法最终调用了C语言的memmove()函数,因此它可以保证同一个数组内元素的正确复制和移动,比一般的复制方法的实现效率要高很多,很适合用来批量处理数组。Java强烈推荐在复制大量数组元素时使用该方法,以取得更高的效率。

Arrays.copyOf()方法有很多重载版本,但实现思路都是一样的,其泛型版本源码如下:

public static  T[]

你可能感兴趣的:(Java集合框架源码解读(1)——ArrayList、LinkedList和Vector)