java ArrayList 源码 解析

时间:2022-02-05 14:01:43
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

    /**
     *  
     *  
内部结构是一个Object类型的数组
成员变量,用来保存数据
    */
    private transient Object[] elementData; 

    /**
     *  
     * 元素的个数。 不是 elementData.length。而是 arraylist.size()
     * 
     */
    private int size;

    /**
     *  
构造器初始化
*/ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); //初始化容量不能小于0,抛出IllegalArgumentException异常 this.elementData = new Object[initialCapacity];//根据参数初始化一个数组,底层是个object数组 } /** *
    构造器 初始化 默认lenght 为10 
*/ public ArrayList() {   this(10);//默认初始容量是10 } /** * */ public ArrayList(Collection<? extends E> c) { elementData = c.toArray();//调用toArray()方法把collection转换成数组 size = elementData.length;//把数组的长度赋值给ArrayList的size属性 if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } /** * 重新分配ArrayList空间为元素多少的真实大小 */ public void trimToSize() { modCount++; int oldCapacity = elementData.length; if (size < oldCapacity) { elementData = Arrays.copyOf(elementData, size); } } /** * 数组长度自增长。如果不够则扩展一半加1*/ 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); } } /** * 数据长度*/ public int size() { return size; } /** * 是否为空*/ public boolean isEmpty() { return size == 0; } /** * 是否包含某个值*/ public boolean contains(Object o) { return indexOf(o) >= 0; } /**
找到数组中第一个相等的值。如果不存在返回-1
*/ 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; } /**
找到数组中最后一个相等的值。如果不存在返回-1
*/ public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; } /** clone一个副本 */ public Object clone() { try { ArrayList<E> v = (ArrayList<E>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { throw new InternalError(); } } /** * 转数组 */ public Object[] toArray() { return Arrays.copyOf(elementData, size); } /** 转换为泛型数组*/ public <T> T[] toArray(T[] a) { if (a.length < size) return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size);//把elementData从索引0开始的size个值 复制到a数组索引为0的位置上 if (a.length > size) a[size] = null; return a; } /** * 获得第几个对应的值从0开始 */ public E get(int index) { RangeCheck(index);//先检查是否越界 return (E) elementData[index]; } /** * 修改对应序号上的值*/ public E set(int index, E element) { RangeCheck(index);//先检查是否越界 E oldValue = (E) elementData[index]; elementData[index] = element; return oldValue; } /** * 添加值
*/ public boolean add(E e) { ensureCapacity(size + 1); //确保长度够大 elementData[size++] = e; return true; } /** * 在摸个位置插入某值*/ public void add(int index, E element) { if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); ensureCapacity(size+1); System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }
API文档中的说明是:将指定的元素插入此列表中的指定位置。向右移动当前位于该位置的元素(如果有)以及所有后续元素(将其索引加 1)。通俗的说法是在指定位置插入元素,指定元素和后面的元素后移。这个方法和set(int index, E element) 不一样,set只是把元素赋值给指定的下标同时返回下标的原先值. set(int index, E element)的判断越界是通过元素的大小来判断的(RangeCheck(index))。add 是 if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); 判断是否越界。



/** * 删除某个位置上的值*/ public E remove(int index) { RangeCheck(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) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work } /**
清空所有值
*/ public void clear() { modCount++; // Let gc do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; } /** * 添加 集合*/ public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacity(size + numNew); System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } /** * 在某个位置插入集合*/ public boolean addAll(int index, Collection<? extends E> c) { if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size); Object[] a = c.toArray(); int numNew = a.length; ensureCapacity(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; } /** * 删除从一定范围内的数据*/ protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // Let gc do its work int newSize = size - (toIndex-fromIndex); while (size != newSize) elementData[--size] = null; } /**
是否超出数组长度
*/ private void RangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); } /***/ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{

int expectedModCount = modCount; s.defaultWriteObject(); s.writeInt(elementData.length); for (int i=0; i<size; i++) s.writeObject(elementData[i]); if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); int arrayLength = s.readInt(); Object[] a = elementData = new Object[arrayLength]; for (int i=0; i<size; i++) a[i] = s.readObject(); } }

 

 Arrays.copyOf 方法:

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {  
  
    T[] copy = ((Object)newType == (Object)Object[].class)  
  
       ? (T[]) new Object[newLength]  
  
       : (T[]) Array.newInstance(newType.getComponentType(), newLength);  
  
    System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));  
  
    return copy;  
  
}  

  arraycopy 方法会因为新数组大小比旧数组大小小而报IndexOutOfBoundsException 

  copyOf 则不会因此报错,因为copyOf 的返回值是在内部new 好的copy 数组,而该copy 数组new 的大小就等于newLength , 

  故即使在客户端指定好了新数组newArray 的大小,接收到返回值后也是指向底层new 出来的数组copy 。换句话说( 也可以因此推出其他的区别) ,在客户端代码中即使不给新数组new 对象,如:String[] newStr = null; 

    那么对于arraycopy 是会报NullPointerException 的错误的,而对于java.util.Arrays 中的copyOf 方法则由于jdk 底层 

    已经new 出了对象而不会报该错误!不过需要特别注意的是:copyOf 方法最后也是调用System.arraycopy 的方法,不过由于前面的准备,异常情况就不会出现了。