1.类在整个java集合体系中的位置
2.继承关系及接口实现
直接继承了AbstractList;
实现了Serializable、List、RandomAccess、Cloneable接口。
3.内部成员变量
-
elementData,一个数组,用于保存列表中的元素;
-
size,记录当前列表中保存元素的个数;
-
modCount,记录列表结构性修改的次数,如add、remove等操作,主要用于检查同时读写产生的错误。
4.重要方法及底层实现
4.1 add(object)
-
首先modCount自增1;
-
其次判断当前数组空间是否能放下新元素; 不能则调用grow方法,扩充数组空间;
-
最后把object放到,size下标指向的空间;
-
size自增1。
上图是grow方法的底层实现,可以看出,在总长度不超过最大长度限制的前提下, 每次增长的空间 = max(minCapacity - oldCapacity, oldCapacity >> 1), 也就是常说的1.5倍扩容。
4.2 add(index, object)
-
首先checkIndex是否在[0, size]内;为什么index=size的时候不抛错,index=size时相当于调用add(object)。
-
modCount自增1;
-
其次判断数组长度是否够用,否则调用grow方法增长;
-
把[index, size)的元素复制到[index+1, size+1)处,即index久右边元素右移一位;
-
object放到index下标指向的空间;
-
size自增1;
4.3 remove(index)
-
checkIndex是否在[0, size)内;
-
modCount自增1, 把[index+1, size)处的元素复制到[index, size-1);
-
size自减1,同时size下标指向的空间赋值null;
4.4 indexOf(object)
顺序遍历判断,如果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增加实际移除的元素数量。