2012-02-03 52 views
0

如何根據對象屬性刪除兩個列表共有的內容。下面我試圖從testList2中刪除與testList1包含相同str1參數的所有值。刪除這兩個列表中共有的內容

我想我可以重寫正在比較的類中的equals方法,因爲在使用removeAll時,等式方法在引擎蓋下使用?

testList1 & testList2是ArrayList類型,都包含一個Test對象列表。

testList1.removeAll(testList2); 

public class Test{ 

    private String str1; 
    private String str2; 

    public Test(String str1 , String str2){ 
     this.str1 = str1; 
     this.str2 = str2; 
    } 

    public String getStr1() { 
     return str1; 
    } 

    public String getStr2() { 
     return str2; 
    } 

    public boolean equals(Object o){ 

     Test t = (Test)o; 
     return this.getStr1().equalsIgnoreCase(t.getStr2()); 

    } 
} 
+0

什麼類是'testList1'(例如' ArrayList','LinkedList',...)? – Thomas 2012-02-03 12:16:29

+0

@Thomas testList1&testList2的類型ArrayList – 2012-02-03 12:17:48

+0

不應該'equals()'比較** this ** **對象作爲參數傳遞的對象嗎?爲什麼你的'equals()'方法比較參數的'str1'和參數'str2'? – mmdemirbas 2012-02-03 12:26:01

回答

1

是的,覆蓋equals(...)應與removeAll(...)一起使用,因爲ArrayList將使用它進行相等性檢查。

引擎蓋下,該方法removeAll(...)AbstractCollection(這是一個超類的ArrayList)將調用contains(entry)上傳遞給removeAll(...)集合。然後contains(...)ArrayList中將使用indexOf(...)獲得元素的索引,然後循環遍歷所有元素並調用equals(...)

這就是說,它變得很明顯的是,removeAll()實現使用列表爲O(N )的複雜性可能得到更大的名單很慢(通過源列表,通過參數列表中的每個條目循環迴路)。

因此,您可能希望將要移除的對象集合傳遞給removeAll(...)。這將導致O(n * log(n))的複雜性(源列表上的循環保持不變,但集合上的調用僅爲O(log(n)))。

1

如果你想從兩個列表中沒有重複那些所有對象(至少我是這樣編輯之前先了解):

Set<Test> both = new HashSet<Test>(); 
both.addAll(testList1); 
both.addAll(testList2); 
//and if you really need to use a List instead of a Set 
List<Test> result = new ArrayList<Test>(both); 

當然,你仍然必須覆蓋equals()如此收藏可以理解你的意思。

+0

這會怎樣解決「刪除常用條目「部分? – Thomas 2012-02-03 12:20:49

+0

您應該添加一些詞語來說明這與問題的關係。 – 2012-02-03 12:21:03

+0

一個集合不允許重複,所以如果你將兩個arraylist添加到集合中,它將只採用唯一的 – Jimmar 2012-02-03 13:16:40

0

我想我可以重寫正在進行比較的類中的equals方法,因爲在使用removeAll時equals方法在引擎蓋下使用?

// you need to compare the current values to the values in t 
public boolean equals(Object o){ 
    Test t = (Test)o; 
    return t.getStr1().equalsIgnoreCase(t.getStr1()) 
      && t.getStr2().equalsIgnoreCase(t.getStr2()); 
} 

我還要做最後的字段,如果你能。

0

如果str1出現在testList1中& testList2,你想從兩個列表中刪除它,對!

// Iterate till all elements 
for (int i=0; i < testList.size()-1; i++) { 
    Test t1 = testList1.get(i); // Get element i of TestList1 Arr 
    Test t2 = testList2.get(i); // Get element i of TestList2 Arr 

    // If t1 & t2 both contains same values in str1 & str2 
    if (t1.equuals(str1) && t2.equals(str1)) { 
     // Remove the elements from list 
     testList1.remove(i); 
     testlist2.remove(i); 
    } 
} 

如果你想覆蓋測試對象等於

// This will comapre current instance and the passed instance 
    public boolean equals(String toCompare, Test obj) { 
    return (this.equals(toComare) && obj.equals(toComapre)); 
    } 

希望這有助於你。使用任何一個方便你的人,兩者都可以工作。

1

首先equals()應該確定兩個對象是否是邏輯上等於。如果這些對象在它們的str1字段相等時在邏輯上相等,那麼您可以使用equals並使用爲集合定義的方法。在這種情況下equals()契約(在java.lang.Object中定義)值得一讀。

如果我和你的代碼進行工作,如果你解決重複你的問題,而不是定義不正確equals()方法,我寧願(警告:沒有經過測試的代碼):

Set<String> strings = new HashSet<String>(listOne.size()); 
for(Test t : listOne){ 
    strings.add(t.getStr1()); 
} 

Iterator<Test> it = listTwo.iterator(); 
while(it.hasNext()){ 
    Test t = it.next(); 
    if(strings.contains(t.getStr1()) 
    it.remove(); 
}