我已经读过关于传递比较器的所有线程,我不明白为什么这个比较器函数违反了规则。如果有人可以清洁我的眼睛,我认为这很简单,但我无法得到它
Stack is:
java.util.TimSort.mergeLo(TimSort.java:747)
java.util.TimSort.mergeAt(TimSort.java:483)
java.util.TimSort.mergeCollapse(TimSort.java:410)
我的对象(简化)
public class SleepDetails {
private DateTime time;
private SleepEnum type;
[...]
}
public enum SleepEnum {
DEEP(0), LIGHT(1), AWAKE(2), BEGIN(16), END(17);
[...]
}
比较器静态成为一个类
Comparator<SleepDetails> comparator = new Comparator<SleepDetails>(){
public int compare(SleepDetails arg0, SleepDetails arg1) {
int res = arg0.getTime().compareTo(arg1.getTime());
if (res != 0)
return res;
if (arg0.getType() == arg1.getType())
return 0;
switch(arg0.getType()) {
case BEGIN:
return -1;
case END:
return 1;
default:
return 0;
}
}
};
主要是我希望按日期对事件进行排序,如果两个事件具有相同的日期时间,则将开始事件放在第一位,将结束事件放在最后。
我没有触发错误的集合
答案 0 :(得分:5)
如果您比较具有相同SleepDetails
的两个getTime()
个实例,其中一个实例有getType()
BEGIN,另一个则为AWAKE。
compare (one, two)
会给-1
而
compare (two, one)
会给0
这违反了合同:
实现者必须确保所有x和y的sgn(compare(x,y))== -sgn(compare(y,x))。
您还必须使用arg1.getType()
方法检查compare
(只要arg0.getType()
既不是BEGIN也不是END)。
public int compare(SleepDetails arg0, SleepDetails arg1) {
int res = arg0.getTime().compareTo(arg1.getTime());
if (res != 0)
return res;
if (arg0.getType() == arg1.getType())
return 0;
switch(arg0.getType()) {
case BEGIN:
return -1;
case END:
return 1;
default:
switch(arg1.getType()) {
case BEGIN:
return 1;
case END:
return -1;
default:
return 0;
}
}
}
答案 1 :(得分:1)
问题是您的代码不区分BEGIN和END以外的类型的枚举值。特别是,当第一个类型既不是BEGIN也不是END时,它返回零,而不管第二个类型。
然而,这种行为并不对称:如果你交换BEGIN和LIGHT对中的两个项目,你会得到-1和0,打破对称性。
您可以将除BEGIN和END之外的所有类型视为彼此相等,但在决定相等时您需要使用双方。