java.util.Set
API 状态:
集合不包含元素对 e1 和 e2 使得 e1.equals(e2)
但据我了解,TreeSet
用于Comparable/Comparator
确定 e1 和 e2 是否重复。我错过了什么吗?
java.util.Set
API 状态:
集合不包含元素对 e1 和 e2 使得 e1.equals(e2)
但据我了解,TreeSet
用于Comparable/Comparator
确定 e1 和 e2 是否重复。我错过了什么吗?
如果compareTo
与equals
(应该)一致,则 TreeSet 是否使用compareTo
或equals
确定相等性都没有关系。来自 JavaDoc:
请注意,如果要正确实现 Set 接口,集合维护的顺序(无论是否提供显式比较器)必须与 equals 一致。(参见 Comparable 或 Comparator 以了解与 equals 一致的精确定义。)这是因为 Set 接口是根据 equals 操作定义的,但 TreeSet 实例使用其 compareTo(或 compare)方法执行所有元素比较,所以两个从集合的角度来看,这种方法认为相等的元素是相等的。一个集合的行为是明确定义的,即使它的顺序与equals不一致;它只是不遵守 Set 接口的一般约定。
该程序将打印“真”,即使equals
总是返回假。但是这个错误实际上是 A 的compareTo
和equals
不一致,并且不是 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 不使用 Comparable/Comparator 来确定 e1 是否等于 e2。Equals 方法是 Object 类的一部分,用于确定集合的两个元素是否相同。即 e1.equals(e2)
但是 Comparable/Comparator 接口用于决定一个元素是否大于、等于或小于其他元素。这在排序期间使用。因此,您唯一需要确保的是 equals 和 compareto 方法是一致的。
因此,比较两个对象使用 equals 方法,并在排序期间使用比较器/可比较
编辑 下面是来自 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
TreeSet
使用比较器。你知道它实际上是通过使用 map 来维护元素的吗?
public TreeSet() {
this(new TreeMap<E,Object>());
}
正如你所说,集合不包含 e1.equals(e2) 这样的元素对 e1 和 e2。这就是 Comparator 有equals
方法的原因。
无论我们将如何使用Set
它都取决于Comparator
. 如果我们使用自己的比较器,我们可以使用Set
asList
但通常我们不这样做。如果我们在初始化时添加自己的对象TreeSet
必须通过或对象必须由Comparator
TreeSet
Comparable
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());
}