(待整理)
RandomAccess 标记接口 空的 支持快速(通常是固定时间)随机访问
标记接口的作用:
为了提升性能,在遍历集合前,我们便可以通过 instanceof 做判断, 选择合适的集合遍历方式,当数据量很大时, 就能大大提升性能。
随机访问列表使用循环遍历,顺序访问列表使用迭代器遍历。
Clonealbe 克隆的标记接口
java.io.Serializable 可序列化标记接口
默认长度为DEFAULT_CAPACITY10
DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是无参默认构造函数构造出来的对象,第一次add后capacity变成10
EMPTY_ELEMENTDATA是为了优化创建ArrayList空实例时产生不必要的空数组,使得所有ArrayList空实例都指向同一个空数组
transient Object[] elementData; 默认不会序列化 因为不一定要把所有elementData都序列化 重写了writeObject()和readObject()只序列化有元素填充的部分
transient 对应 serializble 如果用的是Externalizable就没用
构造函数无参的 就是DEE
有参 >0就new object【参数】 =0 就 EE
<0 非法参数异常
ArrayList(Collection<? extends E> c) 常用的这个:
trimToSize() 资源紧张的时候把后面没用的砍掉 1.5倍的增加嘛
add时 先modCount++ 操作次数加一 跟迭代有关系
没有用ensureCapacity了 直接先判断if (s == elementData.length)
如果满了 grow grow里面再 用mincap newcap 来得到一个新cap(1.5倍原来 和 新 比一比 如果1.5倍大 如果它比array的最大长还大 用新跟array最大长比 若还大就范围intmax 小就返回array最大长;
如果1。5 倍大 但是没有array最大长大 返回1.5倍长
如果 新 大 判断 是 起始状态 返回 新和10里面大的数
不是起始状态返回新 )
size是目前数量
add(index,E)
先check
modCount++
index开始id后面长度后移一个位
加进去 size+1
remove(object)最后还是找到index然后remove(index)
removeall 和 retainall 都是调用 batchremove:
requireNonNull 判对象是否为空 空则报空指针异常
网上的代码都是add里最先检查ensureCapacityInternal,java10里只留了一个ensureCapacity,没被调用,给用户用的,加很多的时候检查用。 Internal这个直接没有了。
contains(o) return indexof(o)>= 0
indexof == null; o.equals(eD[i])
都没 return -1!
lastIndexOf 从后往前找
public!clone方法是 super。clone native 方法 JNI 返回一个
两个toarray
普通的 toarray 就是新建了一个Object的copy然后调用system。arraycopy复制过去
而toarray(T【】 a)
如果arraylist(的size)更长(放不进去a里面) 调用上面那个 相当于 有类型的 只返回一个有类型的array a里面不变
否则 先调用system。arraycopy把elementdata放进a中(改变a)
接着 如果a比size大(一样的话就没有别的操作了)
直接把a【size】置为null 然后返回a
boolean batchRemove(Collection<?> c, boolean complement,
final int from, final int end) {
Objects.requireNonNull©;
final Object[] es = elementData;
int r;
// Optimize for initial run of survivors
for (r = from;; r++) {
if (r == end)
return false;
if (c.contains(es[r]) != complement)
break;
}
int w = r++;
try {
for (Object e; r < end; r++)
if (c.contains(e = es[r]) == complement)
es[w++] = e;
} catch (Throwable ex) {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
System.arraycopy(es, r, es, w, end - r);
w += end - r;
throw ex;
} finally {
modCount += end - w;
shiftTailOverGap(es, w, end);
}
return true;
}
catch部分还没完全理解 其他部分就是判断contain不 跟快排里面的某一种实现方法一样 两个指针index来做
虽然 elementData被transient修饰 不能序列化 但是可以写进objectoutputstream。writeobject
s.writeObject(elementData[i]);
这个值传给了形参 形参没有被transient 所以可以序列化了
size 当cap clone()也是
Fail-Fast机制
注意 remove() 方法会让 expectModcount 和 modcount 相等,所以是不会抛出这个异常。
modCount 用来记录 ArrayList 结构发生变化的次数。结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。
在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 Concurrent Modification Exception。
iterator.remove 前必须iterator.next()