Reputation: 473
I'm using a simple comparator below to sort by start time of a contest, but am getting the error "Comparison method violates its general contract" even though I Covered all the possibilities. Any help on what I'm missing?
Collections.sort(contests, new Comparator<Contest>() {
@Override
public int compare(Contest o1, Contest o2) {
if (o1.getStartTime() != null && o2.getStartTime() != null) {
if (o1.getStartTime().getTime() < o2.getStartTime().getTime()) {
return -1;
}
return 1;
}
return 1;
}
});
Upvotes: 1
Views: 276
Reputation: 887
I don't see any case where it returns 0. And when looking further I see that the return value when 2 objects are compared wich have the same start times will be 1. And because of that the following rule of the contract is violated:
sgn(compare(x, y)) == -sgn(compare(y, x))
If x and y have the same start time. sgn(1) != -sgn(1). In that case the method has to return 0.
Upvotes: 2
Reputation: 1512
If you are running on Java 8, you can use:
List<Contest> sorted = contests.stream()
.sorted(Comparator.comparing(contest -> contest.getStartTime().getTime(), Comparator.nullsFirst(Comparator.naturalOrder())))
.collect(Collectors.toList());
Without knowing details about your startTime data type, assuming time
mathematically comparable from your code, see below for code completeness. Adjust according to your need.
class Sorting {
public static void main(String[] args) {
List<Contest> contests = new ArrayList<>();
contests.add(new Contest(new TimeHolder(1)));
contests.add(new Contest(new TimeHolder(3)));
contests.add(new Contest(new TimeHolder(2)));
List<Contest> sorted = contests.stream()
.sorted(Comparator.comparing(contest -> contest.getStartTime().getTime(), Comparator.nullsFirst(Comparator.naturalOrder())))
.collect(Collectors.toList());
sorted.forEach(contest -> System.out.println(contest.getStartTime().getTime()));
}
static class Contest {
TimeHolder startTime;
public Contest(TimeHolder startTime) {
this.startTime = startTime;
}
public TimeHolder getStartTime() {
return startTime;
}
}
static class TimeHolder{
int time;
public TimeHolder(int time) {
this.time = time;
}
public int getTime() {
return time;
}
}
}
Output:
1
2
3
Upvotes: 0