0

0

0

修罗

站点介绍

只有了解事实才能获得真正的自由

ArrayList源码简读

修罗 2021-11-26 1209 0条评论 JAVASE

首页 / 正文

ArrayList源码简读

Ctrl+鼠标左键进入源码,以下来自jdk11

1637846921270.png

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

ArrayList继承了AbstractList,实现了 List<E>, RandomAccess, Cloneable, Serializable

  • List集合实现RandomAccess接口,就能支持快速随机访问 。
  • 实现 Cloneable接口后,在类中重写Object中的clone方法,然后调用clone方法克隆。
  • 实现了Serializable 接口,这意味着ArrayList支持序列化。

1.1 ArrayList类成员变量

// 序列化验证版本一致
private static final long serialVersionUID = 8683452581122892189L;

// 默认容量
private static final int DEFAULT_CAPACITY = 10;

// 空数组
private static final Object[] EMPTY_ELEMENTDATA = new Object[0];

// 初始化ArrayList的容器
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new Object[0];

// ArrayList集合中的核心数组
transient Object[] elementData;

// 记录数组中存储个数
private int size;

// 数组最大长度(ArrayList中没有用到这个常量,我没搜到)
private static final int MAX_ARRAY_SIZE = 2147483639;

1.2 ArrayList集合类的构造方法

  • 无参数构造方法

文档说ArrayList默认长度为十。其实默认情况为空,调用了add方法才给十。

public ArrayList() {
    // 初始化ArrayList中的elementData为长度为0的空数组。
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
  • 参数为整型的构造方法
public ArrayList(int initialCapacity) {
    // 初始化容量大于0才能构造成功
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else {
        // 传负数则抛异常
        if (initialCapacity != 0) {
            throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
        }
        // 传0
        this.elementData = EMPTY_ELEMENTDATA;
    }

}
  • 参数为Collection对象的构造方法
public ArrayList(Collection<? extends E> c) {
    // 将传入的集合数据拷贝出来,放在当前集合的elementData中
    this.elementData = c.toArray();
    // 传入的集合有数据
    if ((this.size = this.elementData.length) != 0) {
        // 判断传入的集合数据是不是和Object[]一个类型,不是就给他转成Object[]类型
        if (this.elementData.getClass() != Object[].class) {
            this.elementData = Arrays.copyOf(this.elementData, this.size, Object[].class);
        }
    // 传入的集合没有数据
    } else {
        this.elementData = EMPTY_ELEMENTDATA;
    }

}

1.3 ArrayList集合类的方法add()

  • add(E e)
public boolean add(E e) {
    // 此变量来自父抽象类AbstractList,代表ArrayList集合的修改次数。
    ++this.modCount;
    // 调用了重载方法
    this.add(e, this.elementData, this.size);
    return true;
}
  • add(E e, Object[] elementData, int s)
private void add(E e, Object[] elementData, int s) {
    // 容量等于已存数组长度(再添加一个就超长啦)
    if (s == elementData.length) {
        // 扩容
        elementData = this.grow();
    }
    // 添加
    elementData[s] = e;
    this.size = s + 1;
}
  • grow
private Object[] grow() {
    // 调用重载方法
    return this.grow(this.size + 1);
}
  • grow(int minCapacity)
private Object[] grow(int minCapacity) {
    // 老数组扩容后得到新数组,将老数组元素复制给新数组。copyOf内部会创建新数组。
    return this.elementData = Arrays.copyOf(this.elementData, this.newCapacity(minCapacity));
}
  • newCapacity(int minCapacity)

如果new无参构造后一直调用add方法。第一次进newCapacity方法,minCapacity为1,第二次进minCapacity为11。

private int newCapacity(int minCapacity) {
    int oldCapacity = this.elementData.length;
    // 新的容量 = 老 + (老的 / 2)。二进制右移动一位除以2,10进制右移一位除以10,比如:100右移变成10。
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 参数传入的容量比新容量大
    if (newCapacity - minCapacity <= 0) {
        // 地址值相同,第一次扩容,因为扩容一次Arrays.copyOf返回新数组   
        if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // 这里是第一次扩容,默认为10
            return Math.max(10, minCapacity);、
         // 传入扩容长度小于0抛出异常
        } else if (minCapacity < 0) {
            throw new OutOfMemoryError();
        } else {
            // 使用传入参数作为扩容长度
            return minCapacity;
        }
    } else {
        // 计算出来的容量比传入容量大,但需要比2147483639小,否则
        return newCapacity - 2147483639 <= 0 ? newCapacity : hugeCapacity(minCapacity);
    }
}
  • hugeCapacity(int minCapacity)
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) {
        throw new OutOfMemoryError();
    } else {
        return minCapacity > 2147483639 ? 2147483647 : 2147483639;
    }
}

后续待有时间阅读

评论(0)


最新评论

  • 1

    1

  • 1

    1

  • -1' OR 2+158-158-1=0+0+0+1 or 'TKCTZnRa'='

    1

  • 1

    1

  • 1

    1

  • 1

    1

  • 1

    1

  • @@5Qa2D

    1

  • 1

    1

  • 1

    1

日历

2025年09月

 123456
78910111213
14151617181920
21222324252627
282930    

文章目录

推荐关键字: Linux webpack js 算法 MongoDB laravel JAVA jquery javase redis