Set.removeAll()在下面使用哪种方法:equals或compareTo?

时间:2009-05-12 17:32:21

标签: java map set

考虑代码:

class A {

  private int i;

  boolean equals( Object t) {
      if (this == t)
          return true;
      if (!( t instanceof A))
          return false;
      if (this.i == t.i);
  }

}

Map<String,A> orig;
Map<String,B> dup;

我正在尝试这样做

orig.entrySet().removeAll(dup.entrySet());

我看到调用了equals方法;这总是如此,还是可以称之为compareTo?

7 个答案:

答案 0 :(得分:4)

是的,它会调用equals()compareTo()只能在Set 知道包含Comparable个对象时才会使用(例如,排序集可能会这样做)。

答案 1 :(得分:3)

这取决于实施。

例如,HashSet将使用hashCodeequalsTreeSet可能会使用compareTo。最终,只要你的类型表现得恰当,就没关系。

答案 2 :(得分:1)

TreeSet使用compareTo,试试这个:

public class A {

    private int i;

    A(int i) {
        this.i = i;
    }

    @Override
    public boolean equals(Object t) {
        if (this == t)
            return true;
        if (!( t instanceof A))
            return false;
        return (this.i == ((A)t).i);
    }

    public static void main(String[] args) {
        List<A> remove = Arrays.asList(new A(123), new A(789));
        Set<A> set = new TreeSet<A>(new Comparator<A>() {
            @Override
            public int compare(A o1, A o2) {
                return o1.i - o2.i;  
                // return 0; // everything get removed
            }
        });
        set.add(new A(123));
        set.add(new A(456));
        set.add(new A(789));
        set.add(new A(999));

        set.removeAll(remove);
        for (A a : set) {
            System.out.println(a.i);
        }
        System.out.println("done");
    }
}

使比较器始终返回0并且一切都将被删除!如果不使用Comparator但实现Comparable则会发生相同的情况。

TreeSet基于一个TreeMap,它使用getEntry中的compareTo 在TreeSet的Javadoc中,您可以(最后)阅读:

  

... Set接口是根据equals操作定义的,但 TreeSet实例使用compareTo (或compare)方法执行所有元素比较......

[]]

答案 3 :(得分:1)

http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collection.html

“实现可以自由地实现优化,从而避免使用equals调用,例如,首先比较两个元素的哈希码。”

最有可能使用equals,但考虑到上面的陈述,你不能完全依赖equals()来调用。请记住,每当覆盖equals()时,覆盖hashCode()总是一个好主意。

答案 4 :(得分:0)

某些Set实施依赖于hashCode(例如HashSet)。因此,当您覆盖hashCode时,您也应始终覆盖equals

答案 5 :(得分:0)

我知道Java库中唯一不会执行此操作的实现是IdentityHashMap。例如TreeMap没有合适的Comparator

答案 6 :(得分:0)

我没有看到compareTo的使用位置; Map接口的remove()的javadoc说:“更正式地说,如果这个映射包含从键k到值v的映射,使得(key == null?k == null:key.equals(k)),那个映射已移除。”而对于Set接口,它同样说“更正式地,如果集合包含这样的元素,则删除元素e(o == null?e == null:o.equals(e))”。

请注意,removeAll()的javadoc没有说明它是如何运作的,正如其他人所说的那样,这意味着它是一个实现细节。

在Sun的Java中,根据Bloch在他的Effective Java中的说法(如果我没记错的话),它遍历集合并调用remove(),但他强调你绝不能假设它总是如此完成。