删除两个列表共有的内容

时间:2012-02-03 12:09:52

标签: java

如何根据对象属性删除两个列表共有的内容。下面我试图从testList2中删除包含与testList1相同的str1参数的所有值。

我认为我可以覆盖正在比较的类中的equals方法,因为在使用removeAll时使用了equals方法?

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());

    }
}

5 个答案:

答案 0 :(得分: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(),以便收藏品能够理解您的意思。

答案 1 :(得分:1)

是的,覆盖equals(...)应该与removeAll(...)一起使用,因为ArrayList将使用它进行相等性检查。

在幕后,removeAll(...)中的AbstractCollection方法(ArrayList的超类)会在传递给{{1}的集合上调用contains(entry) }}。 removeAll(...)中的contains(...)将使用ArrayList获取元素的索引,indexOf(...)依次循环遍历所有元素,并在其上调用equals(...)

也就是说,很明显使用列表的removeAll()实现具有O(n 2 )复杂度(循环遍历源列表以及通过参数列表的每个条目循环)更大的列表可能会变慢。

因此,您可能希望将要删除的一组对象传递给removeAll(...)。这将导致O(n * log(n))复杂度(源列表上的循环保持不变,但对集合的contains调用仅为O(log(n))。

答案 2 :(得分: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();
}

答案 3 :(得分: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());
}

如果可以的话,我也会将这些字段作为最终字段。

答案 4 :(得分:0)

如果test1中存在str1&amp; 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);
    }
} 

如果要在Test对象中重写equals

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

希望这会对你有所帮助。使用任何方便你的方法都可以。