ArrayList源码剖析

来源:互联网 发布:网络视频监控方案 编辑:程序博客网 时间:2024/06/06 19:49

构造函数:有3个构造函数
1)在jdk源码中ArrayList无参的构造函数,默认初始化大小是10;
2)带有指定大小参数的构造函数
3)带有集合参数的构造函数

一、确定ArrarList的容量
1、若ArrayList的容量不足以容纳当前的全部元素,设置新的容量 = (原始容量 * 3) / 2 + 1。
2、如果扩容后容量还是不够,则直接将minCapacity设置为当前容量。

    public void ensureCapacity(int minCapacity) {         // 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的             modCount++;                          int oldCapacity = elementData.length;          // 若当前容量不足以容纳当前的元素个数,设置新的容量=“(原始容量x3)/2 + 1”          if (minCapacity > oldCapacity) {              Object oldData[] = elementData;                int newCapacity = (oldCapacity * 3)/2 + 1;              //如果还不够,则直接将minCapacity设置为当前容量              if (newCapacity < minCapacity)                    newCapacity = minCapacity;                elementData = Arrays.copyOf(elementData, newCapacity);            }    }

二、添加元素

    public boolean add(E e) {            ensureCapacity(size + 1);    // 确定ArrayList的容量大小        elementData[size++] = e;    // 添加e到ArrayList中        return true;        }
将Element添加到ArrayList的指定位置    
    public void add(int index, E element) {            if (index > size || index < 0)                throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);            ensureCapacity(size+1);          //确定ArrarList的容量           //将index位置及后面的元素都往后移一位        System.arraycopy(elementData, index, elementData, index + 1, size - index);            elementData[index] = element;    //将e添加到index位置        size++;        }

三、获取index位置的元素值

    public E get(int index) {            RangeCheck(index);            return (E) elementData[index];        }

四、设置index位置的值为element

  public E set(int index, E element) {            RangeCheck(index);            E oldValue = (E) elementData[index];            elementData[index] = element;            return oldValue;        }

五、删除ArrayList指定位置的元素

    public E remove(int index) {            RangeCheck(index);                  //检查索引index是否合理        modCount++;            E oldValue = (E) elementData[index];    //保存要删除位置的元素        int numMoved = size - index - 1;        //得到要移动的元素的个数        if (numMoved > 0)                System.arraycopy(elementData, index+1, elementData, index, numMoved);            elementData[--size] = null;             //因为都往后移了一位,所以最后一个元素要置空            return oldValue;    }
删除元素    
 public boolean remove(Object o) {        if (o == null) {            for (int index = 0; index < size; index++)                if (elementData[index] == null) {                    fastRemove(index);                    return true;                }        } else {            for (int index = 0; index < size; index++)                if (o.equals(elementData[index])) {                    fastRemove(index);                    return true;                }        }        return false;}         private void fastRemove(int index) {            modCount++;            int numMoved = size - index - 1;            if (numMoved > 0)         //从"index+1"开始,用后面的元素替换前面的元素。            System.arraycopy(elementData, index+1, elementData, index, numMoved);          elementData[--size] = null;   //将最后一个元素设为nul   }

六、ArrayList是否包含Object(o)

    public boolean contains(Object o) {            return indexOf(o) >= 0;        }

正向查找,返回元素的索引值

    public int indexOf(Object o) {            if (o == null) {                for (int i = 0; i < size; i++)                    if (elementData[i]==null)                        return i;             } else {                 for (int i = 0; i < size; i++)                   if (o.equals(elementData[i]))                        return i;             }             return -1;            }    }

七、返回ArrayList的Object数组

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

八、将集合c追加到ArrayList中

    public boolean addAll(Collection<? extends E> c) {            Object[] a = c.toArray();          //得到集合实际保存元素的数组        int numNew = a.length;            ensureCapacity(size + numNew);  //确定添加集合后ArrayList的容量合理            System.arraycopy(a, 0, elementData, size, numNew);   //利用System.arraycopy方法将数组拷贝到ArrayList集合的数组中         size += numNew;            return numNew != 0;        }

分析ArrayList源码比较重要的几点总结:
1、ArrayList是如何确定容量的—->调用ensureCapacity方法。

2、ArrayList是基于数组的,所以获取元素和设置元素都是这样的形式:elementData[index],只需获取到数组索引就可以了。

3、在ArrayList源码中,大量使用了System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:源数组; srcPos:源数组要复制的起始位置; dest:目的数组; destPos:目的数组放置的起始位置; length:复制的长度。
比如ArrayList的增加、删除、将集合c追加到ArrayList中这三种操作,都使用了这个方法。

4、Arrays类的静态方法:copyOf(T[] original, int newLength)
original - 要复制的数组 ; newLength - 要返回的副本的长度 ; newType - 要返回的副本的类型
比如ArrayList的toArray()方法就使用了Arrays.copyOf方法。

0 0