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

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方法的前世今生《Java集合源码之路-List分析(一)续》)——————————–

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源码:

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

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:反序列化,也是这样。

    原文作者:java集合源码分析
    原文地址: https://blog.csdn.net/angry_tiger/article/details/51011477
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞