ArrayList源码分析1

所有的分析基于JDK15
ArrayList的数据结构是数组。基于数组的实现。是线程不安全的数据结构。实现了List接口。
在这里插入图片描述

属性解释

	 //默认ArrayList的容量
	 private static final int DEFAULT_CAPACITY = 10;
     /** 空数组实例 */
     private static final Object[] EMPTY_ELEMENTDATA = {
    
    };
     /** 共享的空数组实例 */
     private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
    
    };

     /** 数组元素数据 */
     transient Object[] elementData; 
     /** 数组元素个数 */
     private int size;

构造器

ArrayList() 构造一个初始容量为10的空列表。
ArrayList​(int initialCapacity) 构造一个具有指定初始容量的空列表。
ArrayList​(Collection<? extends E> c) 构造一个列表,该列表包含指定集合的​​元素,其顺序由集合的迭代器返回。

API

1 boolean add(E e) 添加元素

public boolean add(E e) {
    
    
        modCount++;
        add(e, elementData, size);
        return true;
}

modCount是ArrayList的父类AbstractList的属性。主要目的是在迭代器iterator在迭代集合的时候不允许对集合结构做修改,如果做了修改,就会报并发修改异常。后续详解。
add的添加在内部方法add(e, elementData, size);中完成。

private void add(E e, Object[] elementData, int s) {
    
    
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

如果元素个数和数组长度相等,就扩容,否则就直接添加元素。数组元素长度+1.来看下扩容的实现,调用grow()方法。

private Object[] grow() {
    
    
        return grow(size + 1);
    }

也是私有的,内部调用grow(int minCapacity)实现。参数是当前容量+1。

private Object[] grow(int minCapacity) {
    
    
		// 获取旧数组的长度
        int oldCapacity = elementData.length;
        //如果旧数组容量>0 或者不为空数组。就开始扩容
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    
    
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
    
    
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
}

如果是空数组,就返回最小容量和默认容量最大值的数组。

elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)

新的容量:

int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1

调用ArraysSupport.newLength方法实现。

public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
    
    
        // assert oldLength >= 0
        // assert minGrowth > 0

        int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
        if (newLength - MAX_ARRAY_LENGTH <= 0) {
    
    
            return newLength;
        }
        return hugeLength(oldLength, minGrowth);
    }

这里的prefGrowth为首选增长率,minGrowth为最小增长率。
minGrowth=minCapacity - oldCapacity
prefGrowth=oldCapacity>>1=0.5oldCapacity.因此实际扩容后的长度为1.5倍的原数组长度。最后进行了数组复制。

elementData = Arrays.copyOf(elementData, newCapacity);

2 void add(int index, E element) 添加元素指定位置

public void add(int index, E element) {
    
    
		//检查索引是否超过数组长度
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);
        elementData[index] = element;
        size = s + 1;
    }

首先检查是否索引越界,然后判断如果元素的数量和数组长度相等,进入逻辑。扩容,然后复制旧的数据,然后赋值操作。

3 boolean addAll​(Collection<? extends E> c) 添加集合

public boolean addAll(Collection<? extends E> c) {
    
    
		//将集合转换为Object数组
        Object[] a = c.toArray();
        modCount++;
        int numNew = a.length;
        if (numNew == 0)
            return false;
        Object[] elementData;
        final int s;
        //如果添加元素的长度大于剩余数组的容量,开始扩容。然后复制数据
        if (numNew > (elementData = this.elementData).length - (s = size))
            elementData = grow(s + numNew);
        System.arraycopy(a, 0, elementData, s, numNew);
        size = s + numNew;
        return true;
    }

4 trimToSize() 将当前数组容量设置为元素的长度

public void trimToSize() {
    
    
        modCount++;
        if (size < elementData.length) {
    
    
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

5 ensureCapacity(int minCapacity) 确保容量

若ArrayList的容量不足以容纳当前的全部元素,设置 新的容量=newLength = Math.max(最小容量-旧数组容量, 旧数组容量/2) + 旧数组容量=1.5旧数组容量

public void ensureCapacity(int minCapacity) {
    
    
        if (minCapacity > elementData.length
            && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
                 && minCapacity <= DEFAULT_CAPACITY)) {
    
    
            modCount++;
            grow(minCapacity);
        }
    }

6 size() 获取数组元素的个数

public int size() {
    
    
      return size;
 }

7 isEmpty() 判断是否为空

public boolean isEmpty() {
    
    
        return size == 0;
}

8 indexOfRange()查找元素

int indexOfRange(Object o, int start, int end) {
    
    
        Object[] es = elementData;
        //如果为空,正向遍历
        if (o == null) {
    
    
            for (int i = start; i < end; i++) {
    
    
                if (es[i] == null) {
    
    
                    return i;
                }
            }
        } else {
    
    
        //不为空,直接遍历
            for (int i = start; i < end; i++) {
    
    
                if (o.equals(es[i])) {
    
    
                    return i;
                }
            }
        }
        return -1;
    }

9 contains 判断是否包含元素

public boolean contains(Object o) {
    
    
		//调用index()方法正向查找
        return indexOf(o) >= 0;
    }

10 indexOf()正向查找

public int indexOf(Object o) {
    
    
        return indexOfRange(o, 0, size);
    }

11 lastIndexOf()逆向查找

 public int lastIndexOf(Object o) {
    
    
        return lastIndexOfRange(o, 0, size);
    }

12 clone

public Object clone() {
    
    
        try {
    
    
        	//调用父类的克隆方法,克隆空的ArrayList实例
            ArrayList<?> v = (ArrayList<?>) super.clone();
            //复制数组,然后赋值
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
    
    
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }

13 Object[] toArray() 转化为数组

public Object[] toArray() {
    
    
        return Arrays.copyOf(elementData, size);
    }

14 get(int index) 获取元素

 public E get(int index) {
    
    
        Objects.checkIndex(index, size);
        return elementData(index);
    }

15 remove(int index) 删除指定位置元素

public E remove(int index) {
    
    
        Objects.checkIndex(index, size);
        final Object[] es = elementData;

        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
        fastRemove(es, index);

        return oldValue;
    }

猜你喜欢

转载自blog.csdn.net/GoSaint/article/details/113871542