0

0

0

修罗

站点介绍

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

ArrayList源码简读

修罗 2021-11-26 1442 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)


最新评论

  • https://www.studyglobus.com/author/carroll34a5552/

    Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.

  • Richardgrold

    1xbet onlayn kazino platforması ilə vaxtınızı daha səmərəli və maraqlı keçirin. Saytın canlı kazino bölməsi istifadəçilərə fərqli bir dünya təklif edir. Burada canlı dilerli kazino oyunlarının hər bir növünü sınaqdan keçirə bilərsiniz. Krupyelərin peşəkarlığı oyunun dinamikasını və marağını artırır. Müntəzəm olaraq yenilənən oyun siyahısı cansıxıcılığa yol vermir. Hesabınızı artırmaq üçün onlarla fərqli və etibarlı üsul mövcuddur. Qazanılan pullar cəmi bir neçə dəqiqə ərzində şəxsi hesabınıza köçürülür. Aktiv fəaliyyətinizə görə fərdi bonuslar və hədiyyələr qazana bilərsiniz. Dəstək xidməti həm çat, həm də e-poçt vasitəsilə kömək göstərir. 1xbet ailəsinə qoşulun və böyük uduşlar üçün ilk addımı atın. onlayn kazino

  • 砂岩白丘

    我一直梦想, 看到你们相册那样的地方。真棒。

  • 城市地標

    我喜欢, 这里分享真实经验。你的项目 就是 属于这里的。请继续。

  • 宗教地標

    我热爱这样的想法, 去那么多国家。真的很鼓舞。

  • 觀景高地

    能感受到热爱。继续保持 感受。

  • 最佳季節

    我关注这样的资源, 写得很实在。你的网站 就是 属于这里的。加油。

  • 1

    1

  • 1

    1

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

    1

日历

2026年07月

   1234
567891011
12131415161718
19202122232425
262728293031 

文章目录

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