集合源码分析----ArrayList

来源:互联网 发布:淘宝支付限额怎么改 编辑:程序博客网 时间:2024/06/08 04:31

分析基于JDK1.7


ArrayList是基于数组实现的,但是底层涉及了很多细节,先看下ArrayList的主要成员

private transient Object[] elementData;//ArrayLis内部存储元素的数组private int size;//数组中包含的元素的大小

构造方法:

    public ArrayList(int initialCapacity) {        super();        if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal Capacity: "+                                               initialCapacity);        this.elementData = new Object[initialCapacity];    }        public ArrayList() {        super();        this.elementData = EMPTY_ELEMENTDATA;    }        public ArrayList(Collection<? extends E> c) {        elementData = c.toArray();        size = elementData.length;        if (elementData.getClass() != Object[].class)            elementData = Arrays.copyOf(elementData, size, Object[].class);    }
可以看到默认的构造方法,其实是创建了一个长度为0的数组(EMPTY_ELEMENTDATA={}),具体扩容操作是在add的时候
而指定大小的就根据大小初始化对应大小的数组

第三个构造方法就是将传进来的集合的元素数组转换为数组初始化elementData,大小赋值给size


add方法:

public boolean add(E e) {    ensureCapacityInternal(size + 1);      elementData[size++] = e;    return true;}private void ensureCapacityInternal(int minCapacity) {    if (elementData == EMPTY_ELEMENTDATA) {        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);    }    ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) {    modCount++;//这个变量参考hashMap    //当add的时候,会判断  加入后  的大小是否大于数组长度,若超过就扩容    if (minCapacity - elementData.length > 0)        grow(minCapacity);}private void grow(int minCapacity) {    int oldCapacity = elementData.length;    int newCapacity = oldCapacity + (oldCapacity >> 1);//大小为原来的两倍    if (newCapacity - minCapacity < 0)        newCapacity = minCapacity;    if (newCapacity - MAX_ARRAY_SIZE > 0)        newCapacity = hugeCapacity(minCapacity);    // 将旧数组的元素放到新数组中    elementData = Arrays.copyOf(elementData, newCapacity);}
前面都是一堆判断,最核心的还是grow操作,这是数组进行扩容的地方,大小变为原来的两倍

所以在使用集合的时候需要考虑数据的大小,如果知道数据的大概范围可以先指定数组的大小,否则太小会进行扩容,性能显然是会有影响的


remove方法:

    public E remove(int index) {        rangeCheck(index);        modCount++;        E oldValue = elementData(index);        int numMoved = size - index - 1;        if (numMoved > 0)            System.arraycopy(elementData, index+1, elementData, index,                             numMoved);        elementData[--size] = null;         return oldValue;    }
逻辑很简单,先取出该位置上的值,然后就是移除了数组中的一个元素后,需要将该位置以后的元素往前移动一个位置


addAll方法:

    public boolean addAll(Collection<? extends E> c) {        Object[] a = c.toArray();        int numNew = a.length;        ensureCapacityInternal(size + numNew);  // Increments modCount        System.arraycopy(a, 0, elementData, size, numNew);        size += numNew;        return numNew != 0;    }
addAll方法也很简单主要是下面几步:

1.将集合c转换成数组a

2.进行扩容

3.将数组a的元素放到elementData上

4.size增加

好吧,主要的方法就这几个,其他不是很难就不说了


0 0
原创粉丝点击