ArrayList源码解析

ArrayList源码解析

1.Arraylist()

Public Arraylist()

初始化一个空的Object[]{}数组集合

2.ArrayList(int initialCapacity)

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);
    }
}

1).若容器入参是否大于0,那么elementData(数组)直接初始化为入参大小
2).若容器入参=0,那么elementData(数组)直接初始化空数组{}
3).其他情况则throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity)

3.ArrayList(Collection<? extends E> c)

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;
    }
}

1).通过c.toArray函数转成Object[]数组
2).将集合大小初始化为a.length,如果数组长度不等于0 则判断数组类型是否为arraylist.class类型,如果是,则将集合数组赋为入参数组
3).负责通过Arrays.copyof方式将数组内容转为Object[]数组,并赋值
4).若入参集合为空,则初始化数组为空集合

4.add(E e)

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
  1. 第一行 ensureCapacityInternal进行数组的扩容,size+1为了保证新数组能满足要求
  2. 第二行则赋值
private void ensureExplicitCapacity(int minCapacity) {
    modCount++; #1
    
       if (minCapacity - elementData.length > 0) #2
        grow(minCapacity); #3
}

#1 modCount表示修改的次数
#2 判断传进来的容量是否大于当前容量
#3 如果满足第二行则进行扩容

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length; #1
    int newCapacity = oldCapacity + (oldCapacity >> 1); #2
    if (newCapacity - minCapacity < 0) #3
        newCapacity = minCapacity; #4
    if (newCapacity - MAX_ARRAY_SIZE > 0) #5
        newCapacity = hugeCapacity(minCapacity); #6
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity); #7
}

#1 获取原数组容量
#2 计算新数组的容量=老数组容量+老数组容量向右移一位(相当于新数组容量为老数组容量的1.5倍)
#3 老数组容量*1.5小于传入新数组的容量
#4则将新数组容量赋值为传入的容量
#5.如果新数组超过了最大数组大小(Integer.MAX_VALUE-8)

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

#6.如果大于Integer.MAX_VALUE()则数组大小设置为Integer.MAX_VALUE,否则设置为MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8)
#7.通过Arrays.copy新生一个数组返回赋值给当前数组

注:
Integer.MAX_VALUE - 8 java数组它不是类,没有对应的class文件,所以数组是由jvm从元素类型合成出来的,所以jvm需要专门的需要通过arrayleng获取所以这个8就是专门用来存储数组长度的

5.add(int index, E element)

public void add(int index, E element) {
    rangeCheckForAdd(index); #1

    ensureCapacityInternal(size + 1); #2 // Increments modCount!!
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);#3
    elementData[index] = element; #4
    size++; #5
}

#1.校验下标是否已超出数组的长度
#2.如果有需要则进行扩容
#3 以传入的节点为起点,之后的节点都往后移一位
#4 赋值
#5 容量+1

private void rangeCheckForAdd(int index) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

在这里插入图片描述

6.set(int index, E element)

public E set(int index, E element) {
    rangeCheck(index);

    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}

此方法比较简单,主要是对下标检验是否越界,指定数组位置进行赋值

7.get(int index)
public E get(int index) {

    rangeCheck(index);

    return elementData(index);
}

此方法比较简单,主要是先校验下标,根据下标获取数组对应的值,得到数据后进行类型强转

8.remove(int index)

public E remove(int index) {
    rangeCheck(index); #1

    modCount++;
    E oldValue = elementData(index); #2

    int numMoved = size - index - 1; #3
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved); #4
    elementData[--size] = null; #5 // clear to let GC do its work

    return oldValue; #6
}

#1.校验传入的数值与数组非空数据数量进行比较,若传入的数据>=数组元素的数量则报数组索引边界异常(throw new indexOutOfBoundsException)
#2.获取index位的值
#3 计算需要移动多少位数组元素
#4 如果需要移动的位数>0则将原数组index+1位开始到numMoved位进行复制并覆盖到原index位上
#5 将元素最后一位赋值为null(去除引用,帮助虚拟机进行垃圾回收)
#6 返回被删除的元素


版权声明:本文为qq_43044287原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。