当前位置: 首页 > 知识库问答 >
问题:

了解Java中的自定义比较器[duplicate]

周培
2023-03-14

我创建了一个自定义比较器,可以按降序对获胜数进行排序,但我不确定它是如何工作的,有人能解释一下这是如何按降序排序的吗?

public static Comparator<FootballClub> sortNumOfWins = new Comparator<FootballClub>() {

    public int compare(FootballClub footballClub1, FootballClub footballClub2) {

        int numOfWins1 = footballClub1.getNumOfWins();
        int numOfWins2 = footballClub2.getNumOfWins();

        /*Returns the number of goals scored in  descending order*/
        return numOfWins2 - numOfWins1;
    }
};

共有3个答案

公孙成仁
2023-03-14

返回值告诉调用方哪个项目“更大”(或者它们是否相等)

1 : numOfWins1 < numOfWins2
0 : numOfWins1 == numOfWins2
-1 : numOfWins1 > numOfWins2

(正1或负1也可以是其他整数,如-2/2,-100/100,任何正/负数)

所以,当你回来的时候:

return numOfWins2 - numOfWins1;

如果 OfWins2,它将是一个正数

如果numOfWins2,则为负数

和0如果numOfWins2==numOfWins1

许高峻
2023-03-14

尝试以下代码:

    public static Comparator<FootballClub> sortNumOfWins = new Comparator<FootballClub>() {

    public int compare(FootballClub footballClub1, FootballClub footballClub2) {

        Integer numOfWins1 = footballClub1.getNumOfWins();
        Integer numOfWins2 = footballClub2.getNumOfWins();

        return numOfWins2.compareTo(numOfWins1);
    }
};

当您仅比较整数字段并且此比较是典型的时,可以使用标准方法 compareTo 从整数类型。

厉熠彤
2023-03-14

Comparator#compare方法的目标是什么?

比较其两个参数的顺序。当第一个参数小于、等于或大于第二个参数时,返回负整数、零或正整数。

给定您的< code >(numofwins 2-numofwins 1)公式:

  • 对于numOfWins1=30和numOf Wins2=20的情况,(20-30)是-10,一个负数。所以第一个应该排在第二个之后
  • 对于numOfWins1=20和numOf Wins2=30的情况,(30-20)是10,一个正数。所以第一个应该排在第二个之上
  • 对于numOfWins1=25和numOf Wins2=25的情况,(25-25)为0,零。因此,这两个项目是并列排序的

下面是一些示例代码。您可以调整Alice和Carol的构造函数,以查看排序操作。

这段代码使用了一个类的新的compact record定义。这是Java 16的一个特性。但是使用< code>record与本答案无关。您也可以使用传统的类定义。

package work.basil.example;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Comparing
{
    public static void main ( String[] args )
    {
        Comparing app = new Comparing();
        app.demo();
    }

    private void demo ( )
    {
        List < FootballClub > clubs =
                List.of(
                        new FootballClub( "Alice" , 25 ) ,
                        new FootballClub( "Bob" , 7 ),
                        new FootballClub( "Carol" , 25 )
                );

        Comparator < FootballClub > sortByWinsDescending = new Comparator < FootballClub >()
        {

            public int compare ( FootballClub footballClub1 , FootballClub footballClub2 )
            {

                int numOfWins1 = footballClub1.wins();
                int numOfWins2 = footballClub2.wins();

                /* Returns the number of goals scored in  descending order */
                return numOfWins2 - numOfWins1;
            }
        };

        List < FootballClub > sorted = new ArrayList <>( clubs );
        sorted.sort( sortByWinsDescending );

        System.out.println( "clubs = " + clubs );
        System.out.println( "sorted = " + sorted );
    }

    record FootballClub(String name , Integer wins)
    {
    }
}

这个代码返回(numOfWins2-numOfWins1);是那种应该避免的“巧妙”编程。这段代码令人困惑和麻烦。我甚至在写这个答案的时候把自己弄糊涂了。

最好是让对象自己比较。在我的示例代码中,我们使用类Integer。嗯,Integer对象已经知道如何比较它们自己。因此,调用Integer#compareTo

return footballClub1.wins().compareTo( footballClub2.wins() ) ;

或者,对于代码中所示的整数基元,调用静态实用工具方法 Integer.compare( int x , int y )

        int numOfWins1 = footballClub1.getNumOfWins();
        int numOfWins2 = footballClub2.getNumOfWins();

        /* Returns the number of goals scored in  descending order */
        return Integer.compare ( numOfWins1 , numOfWins2 ) ;

顺便说一句,我们可以查看OpenJDK源代码,看看这Integer是如何实现的。实现了compare(intx,inty)方法。它们使用一对嵌套的三元运算符。A<代码>:三元是这样工作的:如果谓词测试为true,则使用后面的项,否则为false,请使用后面的项。

// Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved.
// Excerpt from https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/Integer.java
// See licensing terms in that original file.
return (x < y) ? -1 : ((x == y) ? 0 : 1);

养成编写代码的习惯——这是尽可能简单明了的。人类花在阅读代码上的时间比写代码要多得多。在一个作业中,当您的一个报告生成方法中有一个bug,并且您正在半夜进行调试时,您不想试图确定return numOfWins2-numOfWins1是升序还是降序。

作为奖励,人类可读的简单代码通常更有可能成为Java编译器和运行时优化性能的机会。

为了好玩,在return语句之前添加这一行,以查看各个比较。

System.out.println( "numOfWins1: " + numOfWins1 + " | numOfWins2: " + numOfWins2 + " | numOfWins2 - numOfWins1: " + ( numOfWins2 - numOfWins1 ) );

提示: 如果你想要升序而不是降序,只需将调用的结果相乘整数#compareTo整数比较,再乘以负 1 (-1)。这样做会翻转结果的符号,负变为正,正变为负,零保持为零。

return ( -1 * Integer.compare ( numOfWins1 , numOfWins2 ) ) ;  // Ascending rather than descending sort order.

正如Ole V.V.所评论的那样,如果您对lambdas和方法引用感到满意,那么可以通过调用Comparator.comparingInt将整个Comparatorimplementation分解为单行解决方案进行升序排序。

Comparator < FootballClub > sortByWinsDescending = Comparator.comparingInt( FootballClub :: wins );

我们上面的例子变得非常短。

package work.basil.example;


import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Comparing2
{
    public static void main ( String[] args )
    {
        Comparing2 app = new Comparing2();
        app.demo();
    }

    private void demo ( )
    {
        List < FootballClub > clubs =
                List.of(
                        new FootballClub( "Alice" , 20 ) ,
                        new FootballClub( "Bob" , 7 ) ,
                        new FootballClub( "Carol" , 30 )
                );

        Comparator < FootballClub > sortByWinsDescending = Comparator.comparingInt( FootballClub :: wins );

        List < FootballClub > sorted = new ArrayList <>( clubs );
        sorted.sort( sortByWinsDescending );

        System.out.println( "clubs = " + clubs );
        System.out.println( "sorted = " + sorted );
    }

    record FootballClub(String name , Integer wins)
    {
    }
}

 类似资料:
  • 在我的PriorityQueue中,我有两种类型的客户,即VIP和常规客户。我想先为贵宾服务,再为常客服务。 如果CustomerID<100,则视为VIP。 如果客户是VIP,他会排在队列中VIP部分的最后 更新:我不想排序任何其他列除了VIP。我不想添加“日期”,因为它感觉像是一个黑客,而不是理解Java是如何工作的。

  • 问题内容: 我想用自定义排序顺序在Java中创建一个。字符串排序的键需要根据第二个字符进行排序。这些值也是字符串。 样本图: 问题答案: 您可以像这样使用自定义比较器: 样品: 请注意,这只是假设字符在索引1处有一个字符。 另外,您也可以使用以下比较: 通常,此减法“技巧”是无效的,但在这里可以正常使用,因为减法2 不会溢出。 不过,上面的and 解决方案更具可读性。

  • 我想按字母顺序对字段名列表进行排序,但是我需要在比较器的doCompare方法中包含一个条件,以便如果字段名是“pk”,则始终将其排序到列表的顶部。我所拥有的内容如下,但我不确定我是否采取了正确的方法,特别是reurn值为-1000。对此的任何建议都将不胜感激。

  • 问题内容: 为什么无论什么变量成立,它总是返回?即使使用clank搜索变量,它也会返回相同的结果。我错过了什么吗? 我的数组包含逗号分隔的值,我想在数组元素中的逗号之前基于字符串进行搜索。还有其他简单的解决方案吗?我还制作了一个自定义方法,该方法可以遍历数组并找到字符串,但是我正在寻找其他选择。 问题答案: JavaDoc on 声明必须已对数组进行排序,因此比较器实际上将数组值与搜索字符串进行比

  • 下面的代码片段适用于条件1,但不适用于条件2。

  • 问题内容: 我想为汽车清单开发一个排序演示。我正在使用数据表显示汽车列表。现在实际上我想按汽车颜色对列表进行排序。这里不是按字母顺序排序的。我想使用我的自定义排序顺序,例如先是红色汽车,然后是蓝色,等等。 为此,我尝试使用,但它只允许按字母顺序排序。 因此,任何人都可以指导我实现使用该技术的方法,以便使排序变得更快。 问题答案: 我建议你为汽车颜色创建一个枚举,而不要使用字符串,并且枚举的自然顺序