JAVA Collection 源码分析(一)之ArrayList

  到今天为止,差不多已经工作一年了,一直在做的是javaweb开发,一直用的是ssh(sh)别人写好的框架,总感觉自己现在高不成低不就的,所以就像看看java的源码,顺便学习一下大牛的思想和架构,read and write一直是提高自己编程水平的不二法门,写博客只是记录自己的学习历程,方便回顾,写的不好的地方,请多多包含,不喜勿喷,好了废话少说,现在让我们开始我们的历程把,Let’s go!!!!!!!!

  想看源码无从下手,不知道有没有跟我一样感觉的人们,今天用Intellij发现了可以找出类与类之间关系的图,可以让我们可以从上到下,各点击破。推荐给大家。

《JAVA Collection 源码分析(一)之ArrayList》

 

  由于图片太大,我只是截取了一部分图,主要是关于我今天所要分析的ArrayList的类图,从图中我们可以看到最顶层的是Collection接口,Collection接口定义了基本的一些方法,所定义的方法在AbstractCollection中得到了具体的实现,包括size()啊,toArray()….许多基本的方法,大家要是有兴趣的可以去看看源代码。下面我们进入ArrayList中进行具体的分析。

  直接上代码,我们从代码进行分析。

private static final long serialVersionUID = 8683452581122892189L;

    /**
     * 数组初始的容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 其实ArrayList中维护的就是一个Object数组
     */
    private transient Object[] elementData;

    /**
     * 这个size指的不是数组的长度,而是数组中所存储的元素的个数,因为他所采用的是数组动态增长策略,下面我们会看到他的
   * 具体策略的实现。 * *
@serial */ private int size;

  接下来就是ArrayList的初始化,这个我就不贴源码了,public ArrayList(int initialCapacity)第一个初始化方法让你指定初始化容量的大小,public ArrayList(),

无参的初始化方法,他会默认将我们前面EMPTY_ELEMENTDATA = {}赋给elementData,这是我最常用的初始化方法,第三个初始化方法public ArrayList(Collection<? extends E> c)这是将一个实现了Collection接口的类的对象初始化,首先通过toArray方法将其转化成数组赋给elementData,我们直到elementData是一个Object数组,

所以它可以指向任何对象,接下来

if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);

这个很容易理解,如果当前的数组的Class不是Object,则将它转化为Object,按照我的理解就是重新开辟了空间然后让elementData指向它,不知道对不对,请清楚的可以指正我,我会进行修改的。好了,初始化分析完了,让我抽根烟整理整理思路先…..嘿嘿。

  

  我们接着看

  

/**
     * 确保数组容量的策略,首先将数组长度在增加两倍,
* 然后与Integer.MAX_VALUE - 8 进行比较,如果大于 * 的话,则将数组长度増长至Integer.MAX_VALUE,否则就
*/将其赋给Integer.MAX_VALUE-8,防止内存溢出 public void ensureCapacity(int minCapacity) { int minExpand = (elementData != EMPTY_ELEMENTDATA) // any size if real element table ? 0 // larger than default for 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 == 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); }

  

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

  接下来就是常用的一些方法的具体算法实现了,我就不一一举例了,我在这挑上几个我感兴趣的说一说:

  

public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

  我们可以看到,在进行数组的操作的时候,大量的使用到了Arrays.copyOf工具方法,我为了一探究竟,跟踪了进去,看了一下源码,是最后发现其实是调用了一个叫做System.arraycopy的方法,在进去看到这个方法是一个native方法,有可能使用c或者c++写的,因为快吧,这是我的理解。

  

public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

  还有我们看到进行操作的时候大多数都有一个modCount++的操作,这是因为本身ArrayList不是线程安全的,所以在迭代的时候如果没有得到预期值的话,就会fast

fail.这个概念我有点模糊,决定去好好了解一下。

  在进行新增的时候都会进行数组容量的扩展,防止数组出现越界的错误,这也是我们可以从中学习到的一点。

  好了今天就先说这么多,其他的可以去看看源码,睡觉了。。。。。

    原文作者:java源码分析
    原文地址: http://www.cnblogs.com/xz0636/p/3883604.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞