升序和降序排列列表的规则是怎样的?
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
is that it returns less than 0
when the result of comparison is less, greater than 0
when greater and 0
when equal. It is not obvious what the code does. Instead, I would use 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.
)
);
compareTo
与equals
一致
另一个问题是,如果您阅读 Comparable
的 Java 文档,您会发现通常 compareTo
的逻辑最好与equals
.
的逻辑
但是您希望只在 finish
成员字段上进行比较。所以你应该写你的equals
(和hashCode
)也只关注finish
。但这意味着您在问题中看到的最后两个对象将被视为相等,因为它们都共享 9
的 finish
值。我希望你不会认为这两个对象是相等的。
Comparator
在 class 之外定义 Comparator
可能比让 Activity
class 实现 Comparable
.我们将在本答案的其余部分中这样做。
使用 Java 16,我们可以将您的 Activity
class 定义为 record。编译器隐式创建构造函数 getters、equals
& hashCode
和 toString
。使用 record
对这个答案并不重要,但可以使示例代码简短。
package work.basil.example;
public record Activity( int start , int finish )
{
}
Comparator.comparingInt
我们可以使用 predefined comparator for comparing int
values.
而不是定义您自己的 Comparator
接口实现
我们使用 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 ) ,
new Activity( 5 , 9 )
);
该代码生成的列表是 unmodifiable. We want to sort a list, so we need a modifiable list. Feed that unmodifiable list to the constructor of a modifiable implementation of List
such as 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 , 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]]
我一直在尝试了解使用 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
is that it returns less than 0
when the result of comparison is less, greater than 0
when greater and 0
when equal. It is not obvious what the code does. Instead, I would use 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.
)
);
compareTo
与equals
一致
另一个问题是,如果您阅读 Comparable
的 Java 文档,您会发现通常 compareTo
的逻辑最好与equals
.
但是您希望只在 finish
成员字段上进行比较。所以你应该写你的equals
(和hashCode
)也只关注finish
。但这意味着您在问题中看到的最后两个对象将被视为相等,因为它们都共享 9
的 finish
值。我希望你不会认为这两个对象是相等的。
Comparator
在 class 之外定义 Comparator
可能比让 Activity
class 实现 Comparable
.我们将在本答案的其余部分中这样做。
使用 Java 16,我们可以将您的 Activity
class 定义为 record。编译器隐式创建构造函数 getters、equals
& hashCode
和 toString
。使用 record
对这个答案并不重要,但可以使示例代码简短。
package work.basil.example;
public record Activity( int start , int finish )
{
}
Comparator.comparingInt
我们可以使用 predefined comparator for comparing int
values.
Comparator
接口实现
我们使用 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 ) ,
new Activity( 5 , 9 )
);
该代码生成的列表是 unmodifiable. We want to sort a list, so we need a modifiable list. Feed that unmodifiable list to the constructor of a modifiable implementation of List
such as 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 , 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]]