Java – 如果返回值为零,Comparator 如何工作?

huangapple go评论92阅读模式
英文:

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&lt;Map.Entry&lt;Team, Stats&gt;&gt; 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&lt;Map.Entry&lt;Team, Stats&gt;&gt; getLeagueTableEntryComparator() {

    return (Map.Entry&lt;Team, Stats&gt; teamStatsEntryOne, Map.Entry&lt;Team, Stats&gt; teamStatsEntryTwo) -&gt; {

        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)

huangapple
  • 本文由 发表于 2020年8月21日 21:35:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/63523911.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定