英文:
Java - How Does Comparator Work If Return Value Is Zero?
问题
我正试图在Java中编写一个用于根据Comparator
中的值返回条目的平局处理方法。这是抽象方法:
protected abstract Comparator<Map.Entry<Team, Stats>> getLeagueTableEntryComparator();
现在我想要根据积分、进球差和进球数来分隔条目。以下是在单独的类中进行的覆盖方法,通过适当的字段进行比较:
@Override
protected Comparator<Map.Entry<Team, Stats>> getLeagueTableEntryComparator() {
return (Map.Entry<Team, Stats> teamStatsEntryOne, Map.Entry<Team, Stats> teamStatsEntryTwo) -> {
int compare = Integer.compare(teamStatsEntryOne.getValue().getPoints(),
teamStatsEntryTwo.getValue().getPoints());
if (compare == 0) {
compare = Integer.compare(teamStatsEntryOne.getValue().getTotalGoalDifference(),
teamStatsEntryTwo.getValue().getTotalGoalDifference());
if (compare == 0) {
compare = Integer.compare(teamStatsEntryOne.getValue().getGoalsFor(),
teamStatsEntryTwo.getValue().getGoalsFor());
}
return compare;
};
}
然而,很明显,即使在比较了每个字段之后,compare
在最后可能为零。
我的问题是:如果在最后compare=0
,Comparator的实际行为是什么?我是否需要在最后编写一个数字生成器来在两个条目之间实现真正的随机50/50选择?
英文:
I'm trying to write a tiebreaker method in Java that will return an entry based on a value in a Comparator
. This is the abstract method:
protected abstract Comparator<Map.Entry<Team, Stats>> getLeagueTableEntryComparator();
Now I would like to separate the entries based on points, then goal difference, then goals scored. Here's the override method in a separate class, comparing by the appropriate fields:
@Override
protected Comparator<Map.Entry<Team, Stats>> getLeagueTableEntryComparator() {
return (Map.Entry<Team, Stats> teamStatsEntryOne, Map.Entry<Team, Stats> teamStatsEntryTwo) -> {
int compare = Integer.compare(teamStatsEntryOne.getValue().getPoints(),
teamStatsEntryTwo.getValue().getPoints());
if (compare == 0) {
compare = Integer.compare(teamStatsEntryOne.getValue().getTotalGoalDifference(),
teamStatsEntryTwo.getValue().getTotalGoalDifference());
if (compare == 0) {
compare = Integer.compare(teamStatsEntryOne.getValue().getGoalsFor(),
teamStatsEntryTwo.getValue().getGoalsFor());
}
return compare;
};
}
However, it's clear that it is possible for compare
to be zero at the end, even after having compared each field.
My question is this- what is the actual behaviour of the Comparator if comparator=0
at the end? Will I need to write a number generator at the end to achieve a "true" random 50/50 pick between the two entries?
答案1
得分: 4
如果比较器返回 0,则视为两个条目相等。然后由您决定如何处理此信息 - 您可以在两个等效元素之间随机选择,或者对每个元素应用相同的处理(例如,在这种用例中,如果两个团队无法区分,您可以决定在它们之间随机选择,宣布它们共同获胜,甚至决定它们应该进行一场平局的决胜局)。请注意,您不应该在比较器的代码中引入随机部分 - 这将导致比较器的行为变得不确定,并违反常规的比较器约定。
英文:
If the comparator returns 0, the two entries are considered equivalent. It's then up to you to decide what to do with this knowledge - you could randomly choose between the two equivalent elements, or just apply the same treatment to each (e.g., in this usecase, if the two teams are indistinguishable from each other, you could decide to randomly choose between them, declare them as co-champions, or even decide that they should play a tie-breaker game).
Note that you should never introduce a random part in the comparator's code though - this will cause the comparator's behavior to be non-deterministic, and violate the general comparator contract.
答案2
得分: 2
当比较器返回0时发生的行为取决于您如何使用比较器。
如果您在使用比较器对列表进行排序,使用Collections.sort
或者List.sort
,比较器返回0意味着sort
应该保留项目的初始顺序。
如果您想要在这种情况下随机排序,您可以在对列表进行排序之前使用Collections.shuffle
来重新排列列表。这确保了所有“等效”项目具有相同的机会首先出现。
Collections.shuffle(list);
Collections.sort(list, comparator);
Object winner = list.get(0);
如果相反地,您只有两个项目并且想要比较它们,您可以直接调用compare
并且在结果为零时以任何您想要的方式解决平局。例如,对于随机选择,您可以使用Random
类的一个实例。
int compare = comparator.compare(a, b);
Random rnd = new Random();
if (compare == 0) {
if (rnd.nextBoolean()) {
winner = a;
} else {
winner = b;
}
}
英文:
The behavior that happens when comparator returns 0 depends on how you're using the comparator.
If you are using the Comparator to sort a list with Collections.sort
or List.sort
, comparator returning 0 means that sort
should leave the items in their original order.
If you want to randomize the order in this scenario, you can use Collections.shuffle
to reorder the list before sorting it. This guarantees that all "equivalent" items have the same chance of coming out first.
Collections.shuffle(list);
Collections.sort(list, comparator);
Object winner = list.get(0);
If instead you have only two items and want to compare them, you can call compare
directly and break ties in what ever way you want if the result is zero. For example, for a random choice you can use an instance of the Random
class.
int compare = comparator.compare(a, b);
Random rnd = new Random();
if (compare == 0) {
if (rnd.nextBoolean()) {
winner = a;
} else {
winner = b;
}
}
答案3
得分: 0
compare = 0
表示对象相等,不需要交换它们(在排序中)
英文:
compare = 0
mean objects are equal, and it is not necessary to swap them (in sorting)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论