I'm building a program that simulates a sports league, and, oftentimes, I want to sort teams by points, goal differential, etc. to determine things like which team gets promoted or which team gets preferential seeding in a tournament. But, sometimes, teams will be tied on all the criteria that I want to use, and I would like those ties to be broken randomly. I was previously using teams' ids (which are unique ints) to break ties, but I'd like to make it so that no team gets consistent preferential treatment in this sorting. I know that if I just let Java decide which of the tied teams will be placed in front of the other, it'll be very unpredictable, but I don't trust it to be actually random, and I'm worried that it'd inadvertently give some teams an advantage.
I've been using Collections.sort() with comparators to do my sorting, and I recently just went for it, and switched my comparators to use a random number as the final tiebreaker rather than the team ids. Here is the comparator in question:
public static final Comparator<Team> pointsGDRand = new Comparator<Team>() {
public int compare(Team a, Team b) {
int result = b.getStats().getPts() - a.getStats().getPts();
if (result == 0) {
result = b.getStats().getGD() - a.getStats().getGD();
if (result == 0) {
result = R.boolNum();
}
}
return result;
}
};
I think the getter functions are self explanatory, but here's that random function:
public static int boolNum() {
return r.nextBoolean() ? 1 : -1;
}
But, just a bit ago (it look a long time for this error to pop up), I got this error:
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
I've read a little bit, and I think that the problem is likely that I had some instance where it figured out that A > B and B > C, but also A < C. This sheds some light on why it took so long for this error to pop up (it did maybe 20,000 sorts before it popped up with this error), because 2 teams getting the exact same score on all criteria seems like a pretty rare occurrence to me, much less 3 or more.
I'd rather not write my own custom sort, and I'd also rather not shuffle the list in question before each time I sort it (I feel like that'd be inefficient, but I'm confident it would work).
So, how can I make a comparator that breaks ties randomly (such that there's no risk of a team winning tiebreaks disproportionately) without risking that same error again?
Aucun commentaire:
Enregistrer un commentaire