您的位置:首页 > 编程语言 > Java开发

Java集合源码之路-List分析(一)续

2016-03-30 12:29 513 查看
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:反序列化,也是这样。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: