繁体   English   中英

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

[英]How is the rule for sorting a list in ascending order and descending order?

我一直在尝试了解如何使用 Comparable 进行排序。 我有 class 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, 0, 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);
}

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 但这意味着您在问题中看到的最后两个对象将被视为相等,因为它们的finish值都为9 我希望你不认为这两个对象是相等的。

Comparator

在您的 class 之外定义一个Comparator可能比让您的Activity class 实现Comparable更合适。 我们在此答案的 rest 中就是这样做的。

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

package work.basil.example;

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

Comparator.comparingInt

我们可以使用预定义的比较器来比较int,而不是定义您自己的Comparator接口实现。

我们使用使用双冒号字符的方法引用来命名应该用于从我们正在比较的对象中检索 int 的方法。 该方法引用是Activity:: finish 在记录中,默认 getter 方法的名称与属性名称相同,没有常见的get前缀,如 JavaBeans。 所以只需作为方法名称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 ) ,
                new Activity( 5 , 9 )
        );

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

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

请使用实用方法Collections.sort对该新列表进行排序。 如前所述,通过Comparator器。

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

相反,按照降序排列,首先完成9对象,最后完成2 object,我们再次调用Collections.sort 但是我们传递了一个不同的Comparator 我们将原始的 compareInt 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 , 2 ) ,
                new Activity( 3 , 4 ) ,
                new Activity( 0 , 10 ) ,
                new Activity( 5 , 7 ) ,
                new Activity( 8 , 9 ) ,
                new Activity( 5 , 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], Activity[start=5, finish=9]]
activitiesAscending = [Activity[start=1, finish=2], Activity[start=3, finish=4], Activity[start=5, finish=7], Activity[start=8, finish=9], Activity[start=5, finish=9], Activity[start=0, finish=10]]
activitiesDescending = [Activity[start=0, finish=10], Activity[start=8, finish=9], Activity[start=5, finish=9], Activity[start=5, finish=7], Activity[start=3, finish=4], Activity[start=1, finish=2]]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM