remove方法分析
public boolean remove(Object o) {
if (o == null) { //null值单独处理
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
此方法也很简单,简单做一下遍历,然后将遍历到的符合的第一个元素
从数组中去掉,并且将删除元素索引处以后的所有元素依次左移.
上边的本地方法
private void fastRemove(int index) {
modCount++; //为fast-fail机制提供判断依据
int numMoved = size – index – 1; //需要移动的元素数量
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[–size] = null; //告诉gc可以回收这个空间了
}
get方法分析
public E get(int index) {
rangeCheck(index); // 索引合法性检查
return elementData(index);
}
不解释相当简单.
批量remove方法
public boolean removeAll(Collection<?> c) {
return batchRemove(c, false);
}
—————————-(batchRemove方法的前世今生)——————————–
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData; //新建一个不可变引用,指向List的 elementData数组。
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size – r);
w += size – r;
}
if (w != size) {
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size – w;
size = w;
modified = true;
}
}
return modified;
}
探究,既然ArrayList中的elementData成员已经禁止序列化( private transient Object[] elementData;)
那ArrayLIst的数据是如何存储的呢?
卖弄:首先我们要明确一个概念,关于java中的序列化的方式,
java序列化有2种方式:
1) 只是实现了Serializable接口,序列化时,调用java.io.ObjectOutputStream的defaultWriteObject方法,将对象序列化。
注意:此时transient修饰的字段,不会被序列化。
2) 实现了Serializable接口,同时提供了writeObject方法。
序列化时,会调用该类的writeObject方法。而不是java.io.ObjectOutputStream的defaultWriteObject方法。
注意:此时transient修饰的字段,是否会被序列化,取决于writeObject。
分析ArrayList源码:
ArrayList实现了java.io.Serializable,复写了以下2个方法:
private void writeObject(java.io.ObjectOutputStream s)
private void readObject(java.io.ObjectInputStream s)
从源码中可以看出,先调用java.io.ObjectOutputStream的defaultWriteObject方法,进行默认的序列化操作,此时transient修饰的字段,没有被序列化。
接着:for循环,将数组中的元素写出,序列化。而数组中的元素正是transient。
PS:反序列化,也是这样。