首先给一个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++对数组操作速度快。
未完待续。。。