ArrayList读源码心得

  首先给一个ArrayList和LinkedList速度方面的比较

        ArrayList  LinkedList

    增加:    慢      快

    删除:    慢      快

    修改:    快      快

    查询:    快      慢

如果认真阅读LinkedList算法详解就能对LinkedList各方面速度应该有所了解

下面对ArrayList的操作总体介绍,ArrayList所有操作都是建立在他内部封装的一个Object[]数组以及size:

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer.
     */
    private transient Object[] elementData;

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;

这是源码,下面看一下ArrayList的构造函数:

    /**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param   initialCapacity   the initial capacity of the list
     * @exception IllegalArgumentException if the specified initial capacity
     *            is negative
     */
    public ArrayList(int initialCapacity) {
    super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
    this.elementData = new Object[initialCapacity];
    }

这是ArrayLis一个带参数的函数,代表默认加载大小,不能小于0。如果有大数据,添加最好初始化一个比较大的数字,因为ArrayList每次添加都会判断容量够不够,如果不够他就会自动增加为:size/2*3+1也就是增加二分之一,而且还进行copy操作所以首先给一个容量,对性能提升应该很有帮组。

    /**
     * Increases the capacity of this <tt>ArrayList</tt> instance, if
     * necessary, to ensure that it can hold at least the number of elements
     * specified by the minimum capacity argument.
     *
     * @param   minCapacity   the desired minimum capacity
     */
    public void ensureCapacity(int minCapacity) {
    modCount++;
    int oldCapacity = elementData.length;//取到实际长度
        //判断大于实际
    if (minCapacity > oldCapacity) {
        Object oldData[] = elementData;
        int newCapacity = (oldCapacity * 3)/2 + 1;
            if (newCapacity < minCapacity)
        newCapacity = minCapacity;
            //创建一个新长度的数组
            elementData = Arrays.copyOf(elementData, newCapacity);
    }
    }    

添加操作:

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
    ensureCapacity(size + 1);  // 判断下一个数组的length是否有容量
    elementData[size++] = e;
    return true;
    }

看到Add应该就能了解速度慢在什么地方:每次添加都判断长度是否达到,如果没有就行下Array.copy(elements,length);操作,该操作可想而知他的速度。

删除操作:

    public E remove(int index) {
    RangeCheck(index);//检查索引是否>=size,如果大于抛出异常

    modCount++;//这里不讲解,如果需要了解请自行看源码。防止迭代修改和多线程迭代修改
    E oldValue = (E) elementData[index];//返回值

    int numMoved = size - index - 1;//取后半截的长度
        //大于0就执行数组copy操作
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                 numMoved);
    elementData[--size] = null; //最后一个为空

    return oldValue;
    }

其中有句没注释:System.arraycopy(elementData, index+1, elementData, index, numMoved);这也是关键操作,这个方法的作用是:

  把index+1(包括index+1)后面的元素,赋值到index(包括index)后面,index就直接被覆盖。numMoved截取大长度。

修改操作:

    public E set(int index, E element) {
    RangeCheck(index);

    E oldValue = (E) elementData[index];
    elementData[index] = element;
    return oldValue;
    }

修改也是非常快速的。

查询操作:

    public E get(int index) {
    RangeCheck(index);

    return (E) elementData[index];
    }

只接根据根据index查询,数组查询时非常快速的。

这是我实现的MyArrayList:

package servlet;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@SuppressWarnings("unchecked")
public class MyArrayList<T> extends AbstractList<T> implements List<T> {

    private Object[] elements;

    private int size; //reality

    public int size() {

        return size;
    }
    
    
    public MyArrayList(){
        elements=new Object[10];
    }
    
    /*
     * by index modify to t(non-Javadoc)
     * @see java.util.AbstractList#set(int, java.lang.Object)
     */
    public T set(int index,T t){
        rangeCheck(index);
        elements[index]=t;
        return t;
    }
    
    /*
     * by index return elements[index]
     * 
     * @see java.util.AbstractList#get(int)
     */
    public T get(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException("index:" + index + ",size:"
                    + size);
        return (T) elements[index];
    }
    

    /*
     * this list is null
     * 
     * @see java.util.AbstractCollection#isEmpty()
     */
    public boolean isEmpty() {

        return size == 0;
    }

    
    /*
     * to Array(non-Javadoc)
     * 
     * @see java.util.AbstractCollection#toArray()
     */
    public Object[] toArray() {
        return Arrays.copyOf(elements, size);
    }

    
    /*
     * load a to ArrayList
     * 
     * @see java.util.AbstractCollection#toArray(T[])
     */
    
    @SuppressWarnings("hiding")
    public <T> T[] toArray(T[] a) {
        if (a.length > size)
            System.arraycopy(elements, 0, a, 0, elements.length);
        else
            System.arraycopy(elements, 0, a, 0, a.length);
        return a;
    }

    
    /*
     * add element(non-Javadoc)
     * @see java.util.AbstractList#add(java.lang.Object)
     */
    public boolean add(T e) {
        ensureCapcity(size+1);
        elements[size++] = e;
        return true;
    }
    
    
    /*
     * add by index
     */
    public void add(int index,T e){
        if(index < 0 || index>size){
            throw new IndexOutOfBoundsException("index:"+index+" ?");
        }
        Object[] obj=Arrays.copyOf(elements, ++size);
        elements=obj;
        System.arraycopy(elements, index, elements, index+1, size-index-1);//数组前移
        elements[index]=e;
    }
    
    
    /*
     * by o remove
     * 
     * @see java.util.AbstractCollection#remove(java.lang.Object)
     */
    public boolean remove(Object o) {
        if (o != null) {
            for (int index = 0; index < elements.length; index++) {
                if (o.equals(elements[index])) {
                    faceRemove(index);
                    return true;
                }
            }
        } else {
            for (int index = 0; index < elements.length; index++) {
                if (o == (elements[index])) {
                    faceRemove(index);
                    return true;
                }
            }
        }
        return false;
    }
    

    /**
     * remove
     */
    public void faceRemove(int index) {
        rangeCheck(index);
        if (index < size) {
            System.arraycopy(elements, index + 1, elements, index, --size - index);//后移
            elements[size] = null;
        }

    }
    
    
    /*
     * amalgamate collection(non-Javadoc)
     * @see java.util.AbstractCollection#addAll(java.util.Collection)
     */
    public boolean addAll(Collection<? extends T> c) {
        Object[] obj = c.toArray();
        int temp=c.size()+size;
        ensureCapcity(temp);
        System.arraycopy(obj, 0, elements, size, c.size());
        size=temp;
        return true;
    }
    
    
    /*
     * clear(non-Javadoc)
     * @see java.util.AbstractList#clear()
     */
    public void clear() {
        for(int i=0;i<size;i++){
            elements[i] = null;
        }
        size=0;
    }
    
    /*
     * by object query index(non-Javadoc)
     * @see java.util.AbstractList#indexOf(java.lang.Object)
     */
    public int indexOf(Object o) {
        if (o == null)
            for (int index = 0; index < size; index++) {
                if (elements[index] == null) {
                    return index;
                }
            }
        else
            for (int index = 0; index < size; index++) {
                if (elements[index].equals(o)) {
                    return index;
                }
            }
        return -1;
    }
    
    public T remove(int index){
        T temp=(T) elements[index];
        faceRemove(index);
        return temp;
    }
    
    /**
     * 扩充容量
     * 
     * @Author :sheyong
     */
    private void ensureCapcity(int length) {
        if (length > elements.length) {
            int temp = size * 3 / 2+1;
            if (temp < length) {
                temp=length;
            }
            elements = Arrays.copyOf(elements, temp);
        }
    }
    
    /** 
     * @Author : sheyong
     */
    public void rangeCheck(int index){
        if(index<0 || index>=size){
            throw new IndexOutOfBoundsException("index:" +index+" ?");
        }
    }
}

源码下载

ArrayList里面所有操作都是基于System.arraycopy方法,这个方法底层是jni,c++实现,因为c++对数组操作速度快。

未完待续。。。

posted @ 2013-01-29 15:06  JimmyYong  阅读(912)  评论(0编辑  收藏  举报