1、ArrayList存在的意义
我们都知道java中有数组的存在,像 int a[] = {0,1} 这样。 那为什么还要引入java集合?
显然:由于数组的定义,已经是固定的长度,固定的数值。 当我们想要变更这个数组的时候,所需要的成本是很高的,需要先new出新的数组,再将老的数组的值放进去。
2、什么是ArrayList
ArrayList是java.util包下的一个类,数据结构为动态数组,提供相应的方法方便程序猿们使用。
例如:
- add()
- remove()
- foreach
- ...
3、源码分析
- 常量
// 默认数组长度
private static final int DEFAULT_CAPACITY = 10;
/*
数组长度最大值,是int 最大范围-8,这里的-8,笔者认为是有两层含义:
1.数组的头部信息占用了一部分数组空间
2.因为数组插入数据,是需要遍历数组,在末尾插入值。当长度趋近于int最大值时,每插入一条数据,消耗都是比较大的,-8可以提前达到阈值。避免在数组越界边缘疯狂试探。
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
- 创建ArrayList
建议初始化时带上数组长度,避免扩容增加消耗。
- 扩容机制
扩容:即是达到了当前数组的长度的最大值,再往这个数组插入元素时触发。
往下走看这个 ensureCapacityInternal() 方法
再往下
扩容长度计算:
如果初始值是10,转二进制为 1010 + 101 = 10 + 5 = 15
如果初始值是5,转二进制为 101 + 10 = 5 + 2 = 7
故扩容之后的长度是原数组长度的1.5倍
4、JUC 并发
并发的情况下,使用集合。
// 1.用Collections.synchronizedList裹一下
List<Integer> synchronizedList = Collections.synchronizedList(list);
// 2.直接使用JUC下的结合类
CopyOnWriteArrayList<Integer> cwList = new CopyOnWriteArrayList<>();
CopyOnWriteArraySet<Integer> cwSet = new CopyOnWriteArraySet<>();
// 3.使用Vector
Vector<Integer> vector = new Vector<>();