菜鸟初学JDK之ArrayList

初读JDK 1.8 之 2 —-ArrayList


ArrayList 中的几个私有变量

/**
 * Default initial capacity.
 */
 //新建ArrayList 的时候,默认的容量
private static final int DEFAULT_CAPACITY = 10;

/**
 * Shared empty array instance used for empty instances.
 */
 //默认的空集, 用来无参构造ArrayList 是初始化 elementData
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
 * Shared empty array instance used for default sized empty instances. We
 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
 * first element is added.
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer. Any
 * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
 * will be expanded to DEFAULT_CAPACITY when the first element is added.
 */
 //该ArrayList 用来存储数据的地方
transient Object[] elementData; // non-private to simplify nested class access

/**
 * The size of the ArrayList (the number of elements it contains).
 *
 * @serial
 */
 // 该 ArrayList 中已经存储的数据的长度
private int size;

ArrayList 的主要流程

初始化 ArrayList

public ArrayList() {
    //初始化 elementData
       this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
  public ArrayList(Collection c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        //注意这里是有一个bug
        /*
           List list = Arrays.asList("RKd","kd")//这里返回的是一个List子类 是Arrays 的一个私有类(看源码就可以很清楚)
           Object[] oba = list.toArray();  //因为这个私有类的 toArray() 返回的不是 object[] 而是一个 public  T[] toArray(T[] a){}
           System.out.println(oba.getClass());  
           oba[0] = new Object(); // 这里是会抛异常的 
        */
        if (elementData.getClass() != Object[].class)//所以这里要加一个判断,防止 toArray() 返回的不是 object[]
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

add()

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_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;
    //新的容量是 旧的容量的 1.5 倍
    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);
}
//这个方法只是做一个保证.当ArrayList 过于庞大的时候, 确保该ArrayList 可以正常运行或者报错
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}//

add(int index, E element)

 public void add(int index, E element) {
    rangeCheckForAdd(index);//确保index是在合理的范围之内 (大于0 小于size)

    ensureCapacityInternal(size + 1);  // 同上, 可能会对ArrayList 扩容
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);//复制elementData 数组,把  elementData[index] 空出来
    elementData[index] = element;
    size++;
}

remove(int index)

public E remove(int index) {
    rangeCheck(index);//确保index在合理的取值范围内
    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    if (numMoved > 0)
    //System.arraycopy(拷贝的原数据, 原数据的起始坐标, 目标数据,目标数据的起始坐标, 拷贝的长度)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
    return oldValue;
}

remove(Object o)

public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);//同 上面remove 只是没有 rangeCheck(index);没有存储旧数据
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}

get(int index)

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

    return elementData(index);
}

contains(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 总结

ArrayList和LinkedList的区别

  1. 对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。

  2. 在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。

  3. LinkedList不支持高效的随机元素访问。

  4. ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间


ArrayList和Vector 的区别

  1. Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
  2. 当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间。

你可能感兴趣的:(初学java源码)