ArrayList是集合中用的最多的类之一了。一起探究ArrayList的原理吧。
开场
- 值是否可以重复 -> 可以
- 值是否可以为null -> 可以
- 值是否有序 -> 按照插入顺序排列
- 是否是线程安全 -> 否
ArrayList的名字就说明了底层是由array(数组)实现的
1 |
|
三种获取实例的方法
1 |
|
扩容机制
ArrayList也称为’可变数组’集合, 容量自动发生变化的是在向其中添加数据时。
扩容的核心逻辑↓
挺简单的,仔细看就懂了
1 |
|
从底层分析一下下面的代码,以默认容量的方式创建新的ArrayList实例为例;
step1:
1 |
|
此时
1 |
|
add方法底层
1 |
|
step2:
1 |
|
在执行add前,都会去执行ensureCapacityInternal(size + 1);
这个时候,才会将elementData的容量扩展到10(默认容量)
step3:
1 |
|
只检查是否满足该容量最少且能装下所有的元素,不会扩容
其中的一些方法
- System.arrayCopy()
1 |
|
对elementData的操作很多地方都用到了System.arrayCopy()
1 |
|
使用:
1 |
|
- subList(int fromIndex, int toIndex)
消除对ArrayList范围操作的需要
1 |
|
- removeIf(Predicate<? super E> filter)
1 |
|
扩展
1. modCount
在ArrayList中新增,删除,扩容都会出现对该变量的操作;
The number of times this list has been structurally modified(结构化改变). Structural modifications are those that change the size of the list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results. – JDK(AbstractList)
该参数提供fail-first行为.
如果modCount意外地被改变了,iterator(迭代器)或者list iterator(列表迭代器)在响应{@code next}, {@code remove}, {@code previous}, {@code set} or {@code add}操作时,将会抛出 ConcurrentModificationException
对modCount的增加在发生结构化改变时,就是为了得到一个fail-first行为的iterator(和 list iterator)
2. 数组的最大容量
1 |
|
1 |
|
我还是不知道数组的最大容量?
- 数组的下标是int,所以不能超过Integer.MAX_VALUE;
- 其容量还跟自己分配给JVM的大小有关
待我学了 **JVM,看能否回答该问题**
学到了什么
- ArrayList的扩容机制,在每次增加时,会检测容量的大小;扩容至1.5倍
- 推荐使用初始化容量的方式获取实例,减少扩容次数
- 使用无参构造创建对象时,elementData是在第一次add,容量才扩容至10的
对自己的现状不满意只有付出更多的努力去改变它
如果有不对的地方或建议,请指出,谢谢啦