Java 集合类 - ArrayList

164 阅读2分钟

1.类在整个java集合体系中的位置

image.png

2.继承关系及接口实现

直接继承了AbstractList;

实现了Serializable、List、RandomAccess、Cloneable接口。

3.内部成员变量

image.png

  1. elementData,一个数组,用于保存列表中的元素;

  2. size,记录当前列表中保存元素的个数;

  3. modCount,记录列表结构性修改的次数,如add、remove等操作,主要用于检查同时读写产生的错误。

4.重要方法及底层实现

4.1 add(object)

  1. 首先modCount自增1;

  2. 其次判断当前数组空间是否能放下新元素; 不能则调用grow方法,扩充数组空间;

  3. 最后把object放到,size下标指向的空间;

  4. size自增1。

image.png

上图是grow方法的底层实现,可以看出,在总长度不超过最大长度限制的前提下, 每次增长的空间 = max(minCapacity - oldCapacity, oldCapacity >> 1), 也就是常说的1.5倍扩容。

4.2 add(index, object)

  1. 首先checkIndex是否在[0, size]内;为什么index=size的时候不抛错,index=size时相当于调用add(object)。

  2. modCount自增1;

  3. 其次判断数组长度是否够用,否则调用grow方法增长;

  4. 把[index, size)的元素复制到[index+1, size+1)处,即index久右边元素右移一位;

  5. object放到index下标指向的空间;

  6. size自增1;

4.3 remove(index)

  1. checkIndex是否在[0, size)内;

  2. modCount自增1, 把[index+1, size)处的元素复制到[index, size-1);

  3. size自减1,同时size下标指向的空间赋值null;

4.4 indexOf(object)

image.png

顺序遍历判断,如果object是null,用双等号判断,否则调用equals方法,返回第一个符合条件的元素下标。

4.5 addAll(collection)

和add方法差不多,只不过增长的最小空间从1变成了collection的大小;

同时单一下标赋值变成了批量复制collection中的元素到elementData空间中。

modCount自增1, size增加collection.size。

4.6 removeAll(collection)

比较巧妙,用到了双指针;

首先遍历数组,找到第一个被collection包含的元素,把其下标赋给指针a, 然后指针b=a+1; 指针b继续向后移动,如果b指向的元素不被collection包含,那么b指针指向的元素赋值a指向的空间,同时a+=1。即用左移保留元素来压缩移除元素的空间。

modCount增加实际移除的元素数量。