首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Java 容器源码分析之 ArrayList(5)

Java 容器源码分析之 ArrayList(5)

下面再看看如何做到从ArrayList中移除指定容器内的元素以及保留指定容器中的元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* Removes from this list all of its elements that are contained in the
* specified collection.
*/
public boolean removeAll(Collection<?> c) {
    Objects.requireNonNull(c);
    return batchRemove(c, false);
}

/**
* Retains only the elements in this list that are contained in the
* specified collection.  In other words, removes from this list all
* of its elements that are not contained in the specified collection.
*/
public boolean retainAll(Collection<?> c) {
    Objects.requireNonNull(c);
    return batchRemove(c, true);
}

private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData;
    int r = 0, w = 0;
    boolean modified = false;
    try {
        for (; r < size; r++)
            //1) 移除c中元素,complement == false
            //   若elementData[r]不在c中,则保留
            //2)保留c中元素,complement == true
            //   若elementData[r]在c中,则保留
            if (c.contains(elementData[r]) == complement)
                elementData[w++] = elementData[r];
    } finally {
        // Preserve behavioral compatibility with AbstractCollection,
        // even if c.contains() throws.
        // 1)r == size, 则操作成功了
        // 2)r != size, c.contains抛出了异常,
        //      可能是因为元素和c中元素类型不兼容,或者c不支持null元素
        //      则将后面尚未检查的元素向前复制
        if (r != size) {
            System.arraycopy(elementData, r,
                             elementData, w,
                             size - r);
            w += size - r;
        }
        if (w != size) {
            // clear to let GC do its work
            for (int i = w; i < size; i++)
                elementData = null;
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}
我们可以看到,核心的方法在于batchRemove(Collection<?> c, boolean complement),无论是移除给定容器中的元素removeAll(Collection<?> c)还是只保留指定容器中的元素retainAll(Collection<?> c)都是通过该方法来实现的。该方法通过传入的一个布尔类型确定ArrayList中每个元素是否应该保留,详细的注释参见上面代码中的中文注释。
返回列表