微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

列表的升序和降序排序规则是怎样的? Comparator.comparingInt

如何解决列表的升序和降序排序规则是怎样的? Comparator.comparingInt

我一直试图了解使用 Comparable 进行排序的工作原理。我有类 Activity 实现 Comparable 接口。我想了解如何activity.finish-this.finish;按降序排序以及 this.finish-activity.finish 如何按升序排序。我对升序和降序排序首先使用什么感到困惑?

class Activity implements Comparable {
    int start;
    int finish;

    public Activity(int start,int finish) {
        this.start = start;
        this.finish = finish;
    }

    @Override
    public int compareto(Object o) {
        Activity activity = (Activity) o;
        return  activity.finish-this.finish;
    }
}

public class ActivitySelectionProblem {
    public static void main(String[] args) {
        int start[]  =  {1,3,5,8,5};
        int finish[] =  {2,4,10,7,9,9};

        List<Activity> list = new ArrayList<>();
        for(int i = 0 ; i < start.length ; i++){
            list.add(new Activity(start[i],finish[i]));
        }

        Collections.sort(list);
    }
}

解决方法

这很糟糕。 compareTo 的约定是比较结果小于时返回小于 0,大于时大于 0,相等时返回 0。代码的作用并不明显。相反,我会使用 Integer.compare(int,int) - 类似

@Override
public int compareTo(Object o) {
    return Integer.compare(this.finish,((Activity) o).finish);
}
,

Answer by Elliott Frisch 是正确的。此外,请考虑根据您的情况使用 Comparator 而不是 Comparable

tl;博士

Collections.sort(                                       // Utility method for sorting a `List`. 
    activitiesAscending,// A list copied from your original list of inputs.
    Comparator.comparingInt( Activity :: finish )       // A predefined implementation of `Comparator` interface,built for comparing `int` values.    
);                                                      // Results in the passed list being modified,being sorted according to the logic of the passed `Comparator`. 

Collections.sort( 
    activitiesDescending,Collections.reverseOrder(                           // Reverses the sorting logic of the passed `Comparator` object.
        Comparator.comparingInt( Activity :: finish )   // Same `Comparator` as seen above.
    ) 
);

compareToequals

一致

另一个问题是,如果您阅读 Comparable 的 Javadoc,您会发现通常最好使 compareTo 的逻辑与 equals 的逻辑保持一致.

但您希望仅在 finish 成员字段上进行比较。所以你应该写你的 equals(和 hashCode)也只关注 finish。但这意味着您在问题中看到的最后两个对象将被视为相等,因为它们的 9 共享值 finish。我希望您不会认为这两个对象是相等的。

Comparator

在您的类之外定义 Comparator 可能比让您的 Activity 类实现 Comparable 更合适。我们在本回答的其余部分就是这样做的。

使用 Java 16,我们可以将您的 Activity 类定义为 record。编译器隐式创建构造函数、getter、equals & hashCodetoString。使用 record 对这个答案并不重要,但会使示例代码简短。

package work.basil.example;

public record Activity( int start,int finish )
{
}

Comparator.comparingInt

我们可以使用 predefined comparator for comparing int values,而不是定义您自己的 Comparator 接口实现。

我们使用带有双 COLON 字符的 method reference 来命名应该用于从被比较的对象中检索 int 的方法。该方法引用是 Activity :: finish。在记录中,默认的 getter 方法的名称与属性名称相同,没有在 JavaBeans 中常见的 get 前缀。因此,只需将 finish 作为方法名称,而不是 getFinish

Comparator.comparingInt( Activity :: finish ) ) // Method reference from `Activity` being passed to `Comparator` built to compare `int` values.

让我们使用方便的 List.of 语法定义您的输入。

List < Activity > activities =
        List.of(
                new Activity( 1,2 ),new Activity( 3,4 ),new Activity( 0,10 ),new Activity( 5,7 ),new Activity( 8,9 ),9 )
        );

该代码生成的列表是 unmodifiable。我们想对一个列表进行排序,所以我们需要一个可修改的列表。将该不可修改的列表提供给 List 的可修改实现的构造函数,例如 ArrayList

List < Activity > activitiesAscending = new ArrayList <>( activities );

要求实用方法 Collections.sort 对该新列表进行排序。正如我们之前展示的,传递一个 Comparator

Collections.sort( activitiesAscending,Comparator.comparingInt( Activity :: finish ) );

相反,按照降序排列,先是 9 完成对象,最后是 2 完成对象,我们再次调用 Collections.sort。但是我们传递了一个不同的 Comparator。我们将原始的 comparingInt 比较器传递给实用方法 Collections.reverseOrder 以生成新的比较器。

List < Activity > activitiesDescending = new ArrayList <>( activities );
Collections.sort( activitiesDescending,Collections.reverseOrder( Comparator.comparingInt( Activity :: finish ) ) );

整个代码示例。

List < Activity > activities =
        List.of(
                new Activity( 1,9 )
        );

List < Activity > activitiesAscending = new ArrayList <>( activities );
Collections.sort( activitiesAscending,Comparator.comparingInt( Activity :: finish ) );

List < Activity > activitiesDescending = new ArrayList <>( activities );
Collections.sort( activitiesDescending,Collections.reverseOrder( Comparator.comparingInt( Activity :: finish ) ) );

System.out.println( "activities = " + activities );
System.out.println( "activitiesAscending = " + activitiesAscending );
System.out.println( "activitiesDescending = " + activitiesDescending );

运行时。

activities = [Activity[start=1,finish=2],Activity[start=3,finish=4],Activity[start=0,finish=10],Activity[start=5,finish=7],Activity[start=8,finish=9],finish=9]]
activitiesAscending = [Activity[start=1,finish=10]]
activitiesDescending = [Activity[start=0,Activity[start=1,finish=2]]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。