Java List retainAll踩坑記錄

在Java中兩個集合的交集可以使用 List.retainAll(Collection<?> c) 方法,其返回值爲 boolean 類型,官方說明是:

/**
     * Retains only the elements in this list that are contained in the
     * specified collection (optional operation).  In other words, removes
     * from this list all of its elements that are not contained in the
     * specified collection.
     * */

我們不假思索的使用這個返回值進行判斷集合A和集合B是否有交集。
但是注意當兩個集合中的元素相同或者集合沒有變化時,返回結果可能會大跌眼鏡:

List<String> list1= new ArrayList<>();
List<String> list2= new ArrayList<>();
list1.add("haha");
list1.add("heihei");

list2.add("haha");
list2.add("heihei");
boolean isRetain= list1.retainAll(list2);
System.out.println(isRetain);
System.out.println(list1);

講道理應該輸出 true,實際輸出是:

I/System.out: false
I/System.out: [haha, heihei]

翻閱源碼(當前使用的是JDK1.8)

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++)
        	//循環判斷list2中是否包括list1中的元素,將相等的元素放到list1的數組中
        	//其中w就是相等元素的個數,elementData中0至w都是相等的元素
            if (c.contains(elementData[r]) == complement)
                elementData[w++] = elementData[r];
    } finally {

        if (r != size) {
            System.arraycopy(elementData, r,
                             elementData, w,
                             size - r);
            w += size - r;
        }
        //只有相等元素的數量和源集合的數量不一致才能進到這個if中,modified 纔會爲true
        if (w != size) {
            for (int i = w; i < size; i++)
                elementData[i] = null;
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}

發現javadoc說明是:

* @return <tt>true</tt> if this list changed as a result of the call

在這裏插入圖片描述
當兩個集合中的元素相同時,使用retainAll返回的結果是false
因此不能用返回值來判斷兩個集合中是否有交集,作交集運算後,可以使用集合的長度是否 >0來進行判斷交集是否有。

另外,需要注意的是,如果比較的是對象集合的交集,還需要針對該對象處理equals方法和hashCode方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章