您的位置:首页 > 编程语言 > Java开发

JDK12下的ArrayList源码解读

2019-06-03 23:07 3019 查看

ArrayList源码阅读.

//测试代码实现如下
private static void arrayList() {
ArrayList<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add(1, null);
int size = list.size();
for (int i = 0; i < size; i++) {
System.out.println(list.get(i));
}
}

查看

ArrayList<String>();
的源码的时候可以发现如下:

  1. 其属性elementData被初始化为一个空的Object数组.
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

执行

list.add("aaa");
可以看到如下源码:

  1. 其中的size表示目前List中已经存储的元素的数量,目前为0.

  2. 开始执行添加元素操作.

    add(e, elementData, size);

protected transient int modCount = 0;
transient Object[] elementData; // non-private to simplify nested class access
private int size;
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}

进入

add(e, elementData, size);
可以看到如下源码:

  1. 已存储元素和当前的对象数组的长度相等,都是0.

  2. 执行数组扩容行动

    elementData = grow();

  3. 当目前对象数组已满时得到,

    size==elementData.length
    .

  4. 进入

    elementData = grow();
    ,继续扩容.

  5. 通过最后两行代码给对象数组赋值.

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

进入

elementData = grow();
可以看到如下源码:

  1. grow()
    函数 调用
    grow(int minCapacity)
    函数,其中传参的值,是目前需要的最小空间值.

  2. 在经过

    newCapacity
    的计算之后将 新的对象数组的值,copy到elementData中.由此便完成了第一次扩容.

  3. 最小值更新

    minCapacity
    为11

private Object[] grow(int minCapacity) {
return elementData = Arrays.copyOf(elementData,
newCapacity(minCapacity));
}
private Object[] grow() {
return grow(size + 1);
}

进入

newCapacity(minCapacity)
可以看到如下源码:

  1. oldCapacity
    旧容量的值设置为对象数组的长度,
    newCapacity
    新容量的值设置为
    老容量+老容量的一次右移运算
    .

  2. 操作了半个小时结果发现

    newCapacity
    为0,然后进入
    if
    循环,发现目前的elementData一点没动,其地址还是最初的时候赋值的DEFAULTCAPACITY_EMPTY_ELEMENTDATA.

  3. 在默认容量

    DEFAULT_CAPACITY=10
    和最小容量
    minCapacity=1
    之间选择一个最大值,也就是10.作为返回值.

  4. newCapacity
    在经过右移运算后为15 . 然后执行就以15为最新的扩容值为准 返回.

private static final int DEFAULT_CAPACITY = 10;
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity <= 0) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
return Math.max(DEFAULT_CAPACITY, minCapacity);
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return minCapacity;
}
return (newCapacity - MAX_ARRAY_SIZE <= 0)
? newCapacity
: hugeCapacity(minCapacity);
}

总结: 其实就是扩容的操作解读, 赋值很简单. 而且源码的条例就是比我们自己写的好得多.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: