有什么区别:
public FlyingRabbit(){
list = new ArrayList<Sellable>();
}
public void sort(Comparator<Sellable> comp) {
Collections.sort(list, comp);
}
和:
public class CompareCategory implements Comparator<Sellable> {
@Override
public int compare(Sellable s1, Sellable s2) {
return (s1.getCategory()).compareTo(s2.getCategory());
}
}
我很困惑为什么我需要使用比较器
comp
而不是在compare
内使用CompareCategory
。
Collections.sort(List<T>)
根据其元素的自然顺序对给定的
List
进行排序。类可以通过实现 Comparable
接口来定义其自然顺序。该接口提供了一个方法,compareTo()
,它返回:
负整数、零或正整数,因为该对象小于、等于或大于指定对象。
Collections.sort(List<T>, Comparator<T>)
根据给定的List
对Comparator
的元素进行排序。元素的自然顺序被忽略。当 List
的元素已经表现出自然排序,但我们需要按不同的顺序对它们进行排序时,第二种方法会派上用场。
这是一个简短的示例,其中包含
Person
列表。该列表首先按 Person
的自然顺序(lastName
和 name
)排序,然后按给定的 Comparator
进行比较,仅通过 age
进行比较。
class Person implements Comparable<Person> {
private String name;
private String lastName;
private int age;
// Defining Person's natural ordering by creating a comparator that compares by last name and name
private static final Comparator<Person> naturalOrdering = Comparator.comparing(Person::getLastName).thenComparing(Person::getName);
public Person(String name, String lastName, int age) {
this.name = name;
this.lastName = lastName;
this.age = age;
}
public String getName() {
return name;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Person o) {
return naturalOrdering.compare(this, o);
}
@Override
public String toString() {
return String.format("%s %s %d", name, lastName, age);
}
public static void main(String[] args) {
List<Person> list = new ArrayList<>(List.of(
new Person("Luke", "O'Brien", 30),
new Person("Conan", "O'Brien", 25),
new Person("John", "Doe", 50)
));
// Original unordered list
System.out.println(list);
// List ordered by Person's natural ordering (last name and name)
Collections.sort(list);
System.out.println(list);
// List ordered by custom comparator (age)
Collections.sort(list, Comparator.comparing(Person::getAge));
System.out.println(list);
}
}
如果 Sellable 实现了 Comparable 接口,你可以使用 Collections.sort(list)。 否则,您应该创建自己的比较器并使用 Collections.sort(list, comparator)。因为必须有一个规则来比较 Sellable 类型的元素。
当列表中包含的对象实现 Comparable
接口时,您不需要提供
比较器。
这就是 文档定义此接口的用途:
该接口对每个类的对象强加了总排序 实现它。这种排序被称为 class 的 自然排序,类的
方法被称为 其自然的比较方法。compareTo
另一方面, comparator - 是一个对象,用于为没有 natural ordering 的对象集合提供排序,即没有明显的特定方式可以对这些对象进行排序,并且他们的班级没有实现
Comparable
。
当需要根据情况对对象进行不同的排序时,比较器会很方便。例如,您有一个班级
Student
,学生可以按姓名、ID、成绩等进行排序。您可以通过创建一个实现接口 Comparator
的类并覆盖来为每种情况创建一个比较器方法 compare()
(如您列出的代码中所示)或使用静态方法,如 Java 引入的 Comparator.comparing()
8.
话虽如此,接口
Comparator
和Comparable
具有相同的目的(以方便对象的比较),但具有不同的用例。
警告:不要通过在compareTo()
方法中创建比较器
内部将事物混合在一起,如另一个答案中所示。这是一个糟糕的主意。为什么?因为这样的实现将为每次调用此方法创建一个“新的比较器”。要对
10.000.000
元素列表进行排序,需要进行 10.000.000 * log(10.000.000)
比较,每次比较 compareTo()
将被调用,并创建 comparator的新实例。它会对应用程序性能产生负面影响,因为创建对象的成本很高,它需要内存分配,然后给垃圾收集器带来大量工作。 流畅排序
sort()
实用程序类中的静态方法
Collections
,这些方法从早期版本开始就是 JDK 的一部分。您可以在互联网上找到很多代码片段,其中使用了 Collection.sort()
。使用 Java 8 方法 List#sort() 已在 List
接口中引入,您不再需要求助于
Collections
类中的静态方法。相反,您可以直接调用列表上的方法sort()
,请注意,它始终需要比较器作为参数。如果列表中的元素实现了 Comparable
,您应该传递 null
来代替:
如果指定的比较器是null
,则此列表中的所有元素 必须实现
接口和元素的Comparable
natural 应使用订购。myList.sort(null); // only if element of the implement Comparable