java集合-ArrayList

113 阅读2分钟

1、ArrayList存在的意义

我们都知道java中有数组的存在,像 int a[] = {0,1} 这样。 那为什么还要引入java集合?

显然:由于数组的定义,已经是固定的长度,固定的数值。 当我们想要变更这个数组的时候,所需要的成本是很高的,需要先new出新的数组,再将老的数组的值放进去。

2、什么是ArrayList

ArrayList是java.util包下的一个类,数据结构为动态数组,提供相应的方法方便程序猿们使用。

例如:

  1. add()
  2. remove()
  3. foreach
  4. ...

3、源码分析

  1. 常量
// 默认数组长度
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;


  1. 创建ArrayList

Snipaste_2024-03-05_23-31-52.png

image.png

建议初始化时带上数组长度,避免扩容增加消耗。

  1. 扩容机制

扩容:即是达到了当前数组的长度的最大值,再往这个数组插入元素时触发。 Snipaste_2024-03-05_23-47-24.png

往下走看这个 ensureCapacityInternal() 方法 image.png

再往下 image.png

扩容长度计算:

如果初始值是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<>();