我正在尝试实现Comparator的equals方法,但是中途停留。 关于equals()中的描述" sgn(comp1.compare(o1,o2))== sgn(comp2.compare(o1,o2))对于每个对象引用o1和o2。"我应该采用这种方法吗?当我写equals()时,如何知道每个对象引用o1和o2。
Comparator c = new Comparator<Interval>() {
@Override
public int compare(Interval o1, Interval o2) {
return o1.start - o2.start;
}
@Override
public boolean equals(Object obj) {
Type genericType = obj.getClass().getGenericInterfaces()[0];
Type type = ((ParameterizedType) genericType).getActualTypeArguments()[0];
if (((Class<?>) type).getName().equals(Interval.class.getName())) {
// how to implement
// "sgn(comp1.compare(o1,o2))==sgn(comp2.compare(o1, o2))
// for every object reference o1 and o2."
return true;
}
return false;
}
};
答案 0 :(得分:1)
如果比较器以相同的方式对元素进行排序,则可以认为它们是等效的。这个测试可以用于优化排序,但实际上我并不知道核心Java集合利用了这个提示。
未能认识到这种等价可能会消除一些优化的理论机会,但它不会破坏任何东西。因此,通常没有必要覆盖equals()
方法。
正如Comparator.equals()
的文档所说:
请注意总是安全而非才能覆盖
Object.equals(Object)
。
如果您可以将订单定义为类或实例成员,而不是每次使用时都创建新实例,则equals()
的默认基于身份的实现很有效。这样,可以检测到使用相同比较器的两个已排序集合,因为它们的比较器将是相等的。
private static final Comparator<Interval> orderByStart = new Comparator<Interval>() {
@Override
public int compare(Interval o1, Interval o2) {
return o1.start - o2.start;
}
};
我认为这是一个解决方法
没有。这是实现Comparator.equals()
方法的正确方法。
让我们仔细看看你坚持的解决方案:
Comparator<Interval> c = new Comparator<Interval>() {
@Override
public int compare(Interval o1, Interval o2) {
return o1.start - o2.start;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Comparator<?>))
return false;
@SuppressWarnings("unchecked") /* We'll catch this below. */
Comparator<Interval> that = (Comparator<Interval>) obj;
return
IntStream.rangeClosed(Integer.MIN_VALUE, Integer.MAX_VALUE)
.mapToObj(Interval::new)
.allMatch(o1 -> {
return
IntStream.rangeClosed(Integer.MIN_VALUE, Integer.MAX_VALUE)
.mapToObj(Interval::new)
.allMatch(o2 -> {
int sig = Integer.signum(compare(o1, o2));
try {
return Integer.signum(that.compare(o1, o2)) == sig;
} catch (ClassCastException ex) {
return false;
}
});
});
}
};
equals()
的{{1}}方法意味着优化。如果您无法快速有效地测试平等,请不要费心 - “总是安全不”。相反的是 not true:正如我在此处演示的那样,错误地实施Comparator
存在危险。
如果你不能使用正确的习语,你的程序看起来很糟糕,表现更差。