【发布时间】:2012-11-24 12:22:49
【问题描述】:
java.util.Set API 状态:
集合不包含元素对 e1 和 e2 使得 e1.equals(e2)
但据我了解TreeSet 使用Comparable/Comparator 来确定 e1 和 e2 是否重复。我错过了什么吗?
【问题讨论】:
标签: java collections javadoc comparator
java.util.Set API 状态:
集合不包含元素对 e1 和 e2 使得 e1.equals(e2)
但据我了解TreeSet 使用Comparable/Comparator 来确定 e1 和 e2 是否重复。我错过了什么吗?
【问题讨论】:
标签: java collections javadoc comparator
如果compareTo 与equals 一致(应该如此),那么TreeSet 使用compareTo 还是equals 来确定相等性并不重要。来自 JavaDoc:
请注意,由集合维护的顺序(无论是否显式 提供了比较器)必须与equals一致,如果它是 正确实现 Set 接口。 (见可比较或比较 用于与等于一致的精确定义。)就是这样 因为 Set 接口是根据 equals 操作定义的, 但是 TreeSet 实例使用它的执行所有元素比较 compareTo(或比较)方法,因此两个元素被视为相等 通过这种方法,从集合的角度来看,它们是相等的。这 一个集合的行为是明确定义的,即使它的顺序是不一致的 等于;它只是不遵守集合的一般合同 界面。
这个程序将打印'true',即使equals 总是返回false。但错误在于 compareTo 和 equals 对于 A 不一致,并且不是 TreeSet 中的错误。
class A implements Comparable<A> {
public int compareTo(A a) {
return 0;
}
public boolean equals(Object other) {
return false;
}
public static void main(String[] args) {
TreeSet<A> set = new TreeSet<A>();
set.add(new A());
System.out.println(set.contains(new A()));
}
}
【讨论】:
TreeSet 使用比较器。你知道它实际上是通过使用 map 来维护元素的吗?
public TreeSet() {
this(new TreeMap<E,Object>());
}
正如你所说集合不包含元素对 e1 和 e2 使得 e1.equals(e2)。这就是 Comparator 有equals 方法的原因。
无论我们将如何使用Set,它都取决于Comparator。如果我们使用自己的比较器,我们可以将Set 用作List,但通常我们不会这样做。如果我们在TreeSet中添加自己的Object,在初始化TreeSet时必须通过Comparator或者object必须由Comparable实现
可比
具有与另一个对象比较自身能力的可比较对象
比较器
用于比较两个不同的对象。
public int compare(Employee o1, Employee o2) {
// if sort by name
return o1.getName().compareTo(o2.getName());
}
public boolean equals(Object obj) {
// equals with ID
Employee e = (Employee)obj;
return this.getId().equals(e.getId());
}
【讨论】:
你的假设是错误的; TreeSet 不使用 Comparable/Comparator 来确定 e1 是否等于 e2。 Equals 方法是 Object 类的一部分,用于确定集合的两个元素是否相同。即 e1.equals(e2)
但是 Comparable/Comparator 接口用于判断一个元素是否大于、等于或小于其他元素。这在排序期间使用。因此,您唯一需要确保的是 equals 和 compareto 方法是一致的。
所以比较两个对象使用equals方法,排序时使用comparator/comparable
编辑 下面是 JDK 6 的方法定义; AbstractSet 的 equals 方法。 TreeSet 扩展了 AbstractSet
public boolean equals(Object obj)
{
if(obj == this)
return true;
if(!(obj instanceof Set))
return false;
Collection collection = (Collection)obj;
if(collection.size() != size())
return false;
try
{
return containsAll(collection);
}
catch(ClassCastException classcastexception)
{
return false;
}
catch(NullPointerException nullpointerexception)
{
return false;
}
}
http://docs.oracle.com/javase/6/docs/api/java/util/AbstractSet.html
【讨论】: