我有一个类的实例,我想按特定的顺序排序,但也能够使用不同的标准判断一个实例是否存在于一个集合中。例如:
public class Foo {
int x;
int y;
public Foo(int x, int y) { this.x = x; this.y = y }
// equality determined by value of 'x':
@Override
public boolean equals(Object obj) {
if (obj instanceof Foo) {
return ((Foo)obj).x == this.x;
}
return false;
}
@Override
public int hashCode() {
return this.x;
}
@Override
public int compareTo(Foo foo) {
if (this.x < foo.x return -1;
else if (this.x > foo.x return 1;
return 0;
}
}
...
// Would like to keep a set of Foos, but sorted by 'y' value.
// Passing in an explicit comparator which sorts on 'y'.
SortedSet<Foo> test = new TreeSet<Foo>(new ComparatorFoo());
public static class ComparatorFoo implements Comparator<Foo> {
@Override
public int compare(Foo o1, Foo o2) {
if (o1.y < o2.y) return -1;
else if (o1.y > o2.y) return 1;
return 0;
}
}
现在尝试:
test.add(new Foo(3, 4));
test.add(new Foo(1, 2));
test.add(new Foo(5, 6));
// sorts by 'y' ok.
for (Foo foo : test) {
System.out.println(foo.toString());
}
// but can't find an instance with the same 'x' value:
test.contains(new Foo(1, 999));
我是否需要保留两个独立的数据结构才能执行此操作? (一个用于排序,一个用于相等测试?)
谢谢
------更新---------
最终结果:当调用contains()时,用于初始化SortedSet的比较器也会被使用。因此,我无法按照&#39; y&#39;排序,并通过&#39; x&#39;来检查元素是否存在。
答案 0 :(得分:4)
您应该定义与compareTo
equals
从SortedSet
的java doc查看突出显示的部分。
请注意,如果排序集要正确实现Set接口,则排序集维护的排序(无论是否提供显式比较器)必须与equals 一致。 (有关与equals一致的精确定义,请参阅Comparable接口或Comparator接口。)这是因为Set接口是根据equals操作定义的,但是有序集使用compareTo执行所有元素比较(或比较)方法,因此从排序集的角度来看,通过此方法认为相等的两个元素相等。即使排序与equals不一致,排序集的行为也是明确定义的;它只是不遵守Set接口的一般合同。
如下所示更改比较器
public static class ComparatorFoo implements Comparator<Foo> {
@Override
public int compare(Foo o1, Foo o2) {
if (o1.x < o2.x)
return -1;
else if (o1.x > o2.x)
return 1;
return 0;
}
}
它会返回true