retainAll方法簡介
當我們有兩個list集合的時候,我們可以使用retainAll方法求得兩個list集合的子集。retainAll是Collection介面中提供的一個方法,各個實現類有自己的實現方式,我們這裡介紹ArrayList的實現方式。
retainAll原始碼深入
可以看到collection介面中的retainAll方法,需要傳入一個集合。
boolean retainAll(Collection<?> c);
進入arrayList的方法實現。可以看到如下程式碼:
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
由以上程式碼可知,傳入的集合不能為null。接下來看看batchRemove方法。
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++)
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) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
我們看到上述方法的流程如下:
首先獲得當前物件的所有元素,然後通過r和w變數標記兩個集合公共元素的個數。初始化標誌位為false。然後進入迴圈遍歷當前集合,如果傳入的集合中包含當前集合的元素,就直接將這個元素儲存下來。最後到finally塊中,如果r不等於size,證明在迴圈的過程中出現了異常,然後將剩餘的元素進行復制,重新計算陣列的剩餘元素值。如果剩餘的元素值不等於size,則將多餘的位置進行清空。更改modcount的值。這個modcount是父類abstarctlist的值,初始值為0,集合中的內容沒修改一次則增加1。最後重新設定size的大小。返回是否修改值。
retainAll返回值的說明
這裡有兩個說明。
第一個:如果集合A陣列的大小沒有改變,則返回false。如果集合A和集合B是完全相同的集合,也會返回false。
public static void main(String[] args) {
ArrayList<String> list1= new ArrayList<String>();
list1.add("123");
ArrayList<String> list2= new ArrayList<String>();
list2.add("123");
System.out.println(list1.retainAll(list2));
}
如上程式碼會返回false。
第二個:兩個集合沒有交集,會返回true。
public static void main(String[] args) {
ArrayList<String> list1= new ArrayList<String>();
list1.add("123");
ArrayList<String> list2= new ArrayList<String>();
list2.add("12345");
System.out.println(list1.retainAll(list2));
}
如上程式碼會返回true。
總結:當集合A的大小改變的時候返回的是True,大小沒有改變的時候返回的是False。
retainAll的判斷方法
public static void main(String[] args) {
ArrayList<String> list1= new ArrayList<String>();
list1.add("123");
ArrayList<String> list2= new ArrayList<String>();
list2.add("123");
list1.retainAll(list2);
if(list1.size()>0){
System.out.println("有交集");
}else{
System.out.println("沒有交集");
}
}
通過判斷集合的大小,來確定是否存在交集。不能通過方法返回的True和False來判斷。
retainAll的實際效果使用
我們宣告兩個集合,通過呼叫retainAll,保留兩個集合的交集。最後再看輸出的效果。
public static void main(String[] args) {
Collection collection1 = new ArrayList();
collection1.add("a");
collection1.add("b");
collection1.add("c");
Collection collection2 = new ArrayList();
collection2.add("ab");
collection2.add("abc");
collection2.add('a');
System.out.println(collection1);
boolean flag = collection1.retainAll(collection2);
System.out.println(flag);
System.out.println(collection1);
}
執行結果如下:
[a, b, c]
true
[a]
保留了兩個結合的交集。
總結
list的retainAll方法的介紹和分析到此結束,文中難免有不足之處,望大家指正交流。