集合容器ArrayList源码解析

ArrayList源码解析

ArrayList类的注释给我们透露了几点重要信息:
ArrayList是List接口的大小可变数组的实现;
ArrayList允许null元素;
ArrayList的容量可以自动增长;
ArrayList不是同步的;
ArrayList的iterator和listIterator方法返回的迭代器是快速失败的

在这里插入图片描述

属性

// 序列号
private static final long serialVersionUID = 8683452581122892189L;
// ArrayList默认的容量为10个Object元素
private static final int DEFAULT_CAPACITY = 10;
// 指定该ArrayList容量为0时,返回该空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
// 当调用无参构造方法,返回的是该数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 保存添加到ArrayList中的元素
transient Object[] elementData; // non-private to simplify nested class access
// ArrayList中包含的元素数量
private int size;

三种构造方法

// 指定初始容量的空List
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: " +
                initialCapacity);
    }
}
 // 初始化ArrayList实例,则elementData={}
 // 第一次add的时候,elementData将会变成默认的长度:10
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
}
// 构造一个包含指定collection的元素的列表
public ArrayList(Collection<? extends E> c) {
    Object[] a = c.toArray();
    if ((size = a.length) != 0) {
        if (c.getClass() == ArrayList.class) {
            elementData = a;
        } else {
            elementData = Arrays.copyOf(a, size, Object[].class);
        }
    } else {
        // replace with empty array.
        elementData = EMPTY_ELEMENTDATA;
    }
}

add()方法
grow(int minCapacity)扩容量方法

/**
 * 新增元素操作
 *
 * List list = new ArrayList();
 * list.add("a1");
 */
// eg1:第一次新增元素e="a1"
public boolean add(E e) {
    /** 确定是否需要扩容,如果需要,则进行扩容操作*/
    ensureCapacityInternal(size + 1);  // Increments modCount!!

    // eg1:size=0,elementData[0]="a1",然后a自增为1
    elementData[size++] = e;
    return true;
}
// eg1:第一次新增元素,所以size=0,则:minCapacity=size+1=1
private void ensureCapacityInternal(int minCapacity) {
    // eg1:第一次新增元素,calculateCapacity方法返回值为DEFAULT_CAPACITY=10
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}  

/**
 * 确保明确的ArrayList的容量
 *
 * @param minCapacity ArrayList所需的最小容量
 */
// eg1:第一次新增元素,minCapacity=10
private void ensureExplicitCapacity(int minCapacity) {
    // eg1: modCount++后,modCount=1
    modCount++;

    /** 如果所需的最小容量大于elementData数组的容量,则进行扩容操作 */
    if (minCapacity - elementData.length > 0) { // eg1:10-0=10,满足扩容需求
        // eg1:minCapacity=10
        grow(minCapacity);
    }
}
/**
 * Increases the capacity to ensure that it can hold at least the
 * number of elements specified by the minimum capacity argument.
 *
 * 扩容操作
 *
 * @param minCapacity 所需要的最小扩容量
 */
// eg1:第一次新增元素,minCapacity=10,即:需要将elementData的0长度扩容为10长度。
private void grow(int minCapacity) {

    /** 原有数组elementData的长度*/
    int oldCapacity = elementData.length; // eg1:oldCapacity=0

    /**
     * A >> 1 等于 A/2
     * eg: 3 >> 1 = 3/2 = 1
     *     4 >> 1 = 4/2 = 2
     * ------------------------
     * A << 1 等于 A*2
     * eg: 3 << 1 = 3*2 = 6
     *     4 << 1 = 4*2 = 8
     *
     * 000100 >> 1 = 000010
     * 000100 << 1 = 001000
     */
    /** 新增oldCapacity的一半整数长度作为newCapacity的额外增长长度 */
    int newCapacity = oldCapacity + (oldCapacity >> 1); // eg1:newCapacity=0+(0>>1)=0

    /** 新的长度newCapacity依然无法满足需要的最小扩容量minCapacity,则新的扩容长度为minCapacity */
    if (newCapacity - minCapacity < 0) {
        // eg1:newCapacity=10
        newCapacity = minCapacity;
    }

    /** 新的扩容长度newCapacity超出了最大的数组长度MAX_ARRAY_SIZE */
    if (newCapacity - MAX_ARRAY_SIZE > 0) {
        newCapacity = hugeCapacity(minCapacity);
    }

    /** 扩展数组长度为newCapacity,并且将旧数组中的元素赋值到新的数组中 */
    // eg1:newCapacity=10, 扩容elementData的length=10
    elementData = Arrays.copyOf(elementData, newCapacity);
}

private static int hugeCapacity(int minCapacity) {
   if (minCapacity < 0) { // overflow
       throw new OutOfMemoryError();
   }
   return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}

get()方法 set()方法

/**
 * Returns the element at the specified position in this list.
 *
 * @param index index of the element to return
 * @return the element at the specified position in this list
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

/**
 * Replaces the element at the specified position in this list with
 * the specified element.
 *
 * @param index   index of the element to replace
 * @param element element to be stored at the specified position
 * @return the element previously at the specified position
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E set(int index, E element) {
    /** 判断index是否超出了ArrayList中包含的元素数量,如果超出,则抛出IndexOutOfBoundsException异常 */
    rangeCheck(index);

    /** 获得index下标对应的旧值 */
    E oldValue = elementData(index);

    /** 将index下标对应的值,赋值为新值——element */
    elementData[index] = element;

    /** 返回index下标对应的旧值 */
    return oldValue;
}
/**
 * Checks if the given index is in range.  If not, throws an appropriate
 * runtime exception.  This method does *not* check if the index is
 * negative: It is always used immediately prior to an array access,
 * which throws an ArrayIndexOutOfBoundsException if index is negative.
 */
// eg1:index=0
private void rangeCheck(int index) {
    if (index >= size) {
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
}

removeAll()方法

public boolean removeAll(Collection<?> c) {
    Objects.requireNonNull(c);
    return batchRemove(c, false);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData;
    int r = 0, w = 0;
    boolean modified = false;
    try {
        for (; r < size; r++) {
            if (c.contains(elementData[r]) == complement) {
                elementData[w++] = elementData[r];
            }
        }
    } finally {
        // Preserve behavioral compatibility with AbstractCollection,
        // even if c.contains() throws.
        if (r != size) {
            System.arraycopy(elementData, r,
                    elementData, w,
                    size - r);
            w += size - r;
        }
        if (w != size) {
            // clear to let GC do its work
            for (int i = w; i < size; i++) {
                elementData[i] = null;
            }
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}

/**
 * 删除元素
 */
// eg1:elementData中保存了{"a1","a2","a3","a4"},删除第一个元素,即:index=0
public E remove(int index) {
    /** 校验传入的参数index是否超出了数组的最大下标,如果超出,则抛出:IndexOutOfBoundsException异常*/
    rangeCheck(index);

    /** 集合的修改次数加1 */
    modCount++;

    // eg1:String oldValue="a1"
    /** 获得index下标对应的旧值oldValue */
    E oldValue = elementData(index);

    // eg1:numMoved=4-0-1=3
    /** 获得需要移动元素的个数 */
    int numMoved = size - index - 1;
    if (numMoved > 0) {
        /**
         * {"a1","a2","a3","a4"}
         *
         * 假设删除"a2",那么index=1, numMoved=2, 那么下面的语句执行的就是:
         * 将第一个入参的elementData从第2位"a3"(index+1)开始复制2位(numMoved)即:"a3","a4";
         * 复制到第三个入参elementData的第1位(index),即elementData变成 {"a1","a3","a4","a4"}
         */
        System.arraycopy(elementData, index + 1, elementData, index, numMoved);
    }
    /** 通知jvm将之前的最后一位元素进行垃圾回收 */
    elementData[--size] = null; // clear to let GC do its work

    /** 返回已被删除的元素 */
    return oldValue;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值