Java - 如果 Return 值为零,比较器如何工作?
Java - How Does Comparator Work If Return Value Is Zero?
我正在尝试在 Java 中编写一个决胜方法,它将 return 基于 Comparator
中的值的条目。这是抽象方法:
protected abstract Comparator<Map.Entry<Team, Stats>> getLeagueTableEntryComparator();
现在我想根据得分、净胜球差和进球数来区分条目。这是单独 class 中的覆盖方法,通过适当的字段进行比较:
@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
最后可能为零,即使在比较了每个字段之后也是如此。
我的问题是 - 如果最后 comparator=0
,比较器的实际行为是什么?我是否需要在最后编写一个数字生成器以在两个条目之间实现“真正的”随机 50/50 选择?
compare = 0
表示对象相等,无需交换(排序时)
如果比较器returns为0,则认为这两个条目是等价的。然后由您决定如何处理这些知识——您可以在两个等效元素之间随机选择,或者对每个元素应用相同的处理(例如,在这个用例中,如果两个团队彼此无法区分,您可以决定在他们之间随机选择,宣布他们为 co-champions,甚至决定他们应该玩 tie-breaker 游戏)。
请注意,您永远不应在比较器的代码中引入随机部分 - 这将导致比较器的行为成为 non-deterministic,并违反一般比较器合同。
比较器 returns 0 时发生的行为取决于您如何使用比较器。
如果您使用比较器对包含 Collections.sort
或 List.sort
的列表进行排序,则比较器返回 0 意味着 sort
应保留项目的原始顺序。
如果您想在这种情况下随机排列顺序,可以在排序前使用Collections.shuffle
对列表重新排序。这保证了所有“等价”的项目都有相同的机会首先出现。
Collections.shuffle(list);
Collections.sort(list, comparator);
Object winner = list.get(0);
如果您只有两个项目并且想要比较它们,您可以直接调用 compare
并在结果为零时以您想要的任何方式打破平局。例如,对于随机选择,您可以使用 Random
class.
的实例
int compare = comparator.compare(a, b);
Random rnd = new Random();
if (compare == 0) {
if (rnd.nextBoolean()) {
winner = a;
} else {
winner = b;
}
}
我正在尝试在 Java 中编写一个决胜方法,它将 return 基于 Comparator
中的值的条目。这是抽象方法:
protected abstract Comparator<Map.Entry<Team, Stats>> getLeagueTableEntryComparator();
现在我想根据得分、净胜球差和进球数来区分条目。这是单独 class 中的覆盖方法,通过适当的字段进行比较:
@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
最后可能为零,即使在比较了每个字段之后也是如此。
我的问题是 - 如果最后 comparator=0
,比较器的实际行为是什么?我是否需要在最后编写一个数字生成器以在两个条目之间实现“真正的”随机 50/50 选择?
compare = 0
表示对象相等,无需交换(排序时)
如果比较器returns为0,则认为这两个条目是等价的。然后由您决定如何处理这些知识——您可以在两个等效元素之间随机选择,或者对每个元素应用相同的处理(例如,在这个用例中,如果两个团队彼此无法区分,您可以决定在他们之间随机选择,宣布他们为 co-champions,甚至决定他们应该玩 tie-breaker 游戏)。
请注意,您永远不应在比较器的代码中引入随机部分 - 这将导致比较器的行为成为 non-deterministic,并违反一般比较器合同。
比较器 returns 0 时发生的行为取决于您如何使用比较器。
如果您使用比较器对包含 Collections.sort
或 List.sort
的列表进行排序,则比较器返回 0 意味着 sort
应保留项目的原始顺序。
如果您想在这种情况下随机排列顺序,可以在排序前使用Collections.shuffle
对列表重新排序。这保证了所有“等价”的项目都有相同的机会首先出现。
Collections.shuffle(list);
Collections.sort(list, comparator);
Object winner = list.get(0);
如果您只有两个项目并且想要比较它们,您可以直接调用 compare
并在结果为零时以您想要的任何方式打破平局。例如,对于随机选择,您可以使用 Random
class.
int compare = comparator.compare(a, b);
Random rnd = new Random();
if (compare == 0) {
if (rnd.nextBoolean()) {
winner = a;
} else {
winner = b;
}
}