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

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, SerializableArrayList继承了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;
}
}
Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.
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