简体   繁体   English

Collections.sort(list) 和 Collections.sort(list,comparator) 的区别

[英]Difference between Collections.sort(list) and Collections.sort(list,comparator)

What's the difference between:有什么区别:

    public FlyingRabbit(){
        list = new ArrayList<Sellable>();
    }
    public void sort(Comparator<Sellable> comp) {
        Collections.sort(list, comp);
    }

and:和:

public class CompareCategory implements Comparator<Sellable> {
    @Override
    public int compare(Sellable s1, Sellable s2) {
            return (s1.getCategory()).compareTo(s2.getCategory());
    }
}

I'm confused about why do I need to use the Comparator comp instead of using compare inside CompareCategory .我很困惑为什么我需要使用 Comparator comp而不是在CompareCategory中使用compare

Collections.sort(List<T>) sorts the given List by the natural ordering of its elements. Collections.sort(List<T>)按照其元素的自然顺序对给定的List进行排序。 The natural ordering of an object can be defined by implementing the Comparable interface in the corresponding class. This interface provides a single method, compareTo , which returns object 的自然顺序可以通过在相应的 class 中实现Comparable接口来定义。该接口提供了一个方法compareTo ,它返回

a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.负数 integer、零或正数 integer,因为此 object 小于、等于或大于指定的 object。

On the other hand, Collections.sort(List<T>, Comparator<T>) orders the List 's elements according to the given Comparator .另一方面, Collections.sort(List<T>, Comparator<T>)根据给定的ComparatorList的元素进行排序。 Their natural ordering will be ignored for the sorting.排序时将忽略它们的自然顺序。 This second method comes in hand when the List 's elements already possess their natural ordering but we want to order them by a different criteria.List的元素已经拥有它们的自然顺序但我们想按不同的标准对它们进行排序时,第二种方法就派上用场了。

Here's a simple example with a Person class displaying name, last name and age.这是一个简单的示例,其中显示姓名Person的姓名和年龄。

class Person implements Comparable<Person> {
    private String name, lastName;
    private int age;

    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) {
        //Defining Person's natural ordering by creating a comparator and comparing by last name and then name the current object and the given paramter 
        return Comparator.comparing(Person::getLastName).thenComparing(Person::getName).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("Matt", "O'Brien", 30),
                new Person("Conan", "O'Brien", 25),
                new Person("Frank", "Johnson", 50)
        ));

        //Original unordered list
        System.out.println(list);

        //List ordered by Person's natural ordering (last name and then name)
        Collections.sort(list);
        System.out.println(list);

        //List ordered by custom criteria (age)
        Collections.sort(list, Comparator.comparing(Person::getAge));
        System.out.println(list);
    }
}

If Sellable implements the interface Comparable you can use Collections.sort(list).如果 Sellable 实现了 Comparable 接口,您可以使用 Collections.sort(list)。 Otherwise you should create own Comparator and use Collections.sort(list, comparator).否则你应该创建自己的 Comparator 并使用 Collections.sort(list, comparator)。 Because there must be a rule by which to compare elements of the Sellable type.因为必须有一个规则来比较 Sellable 类型的元素。

You don't need to provide a comparator when objects contained in the list implement Comparable interface.当列表中包含的对象实现Comparable接口时,您不需要提供比较器

Comparator & Comparator比较器与比较器

That's how the purpose of this interface defined by the documention :这就是文档定义此接口的目的:

This interface imposes a total ordering on the objects of each class that implements it.该接口对实现它的每个 class 的对象强加了总排序。 This ordering is referred to as the class's natural ordering , and the class's compareTo method is referred to as its natural comparison method.此排序称为类的自然排序,类的compareTo方法称为其自然比较方法。

On the other hand, comparator - is an object that is used to provide an ordering for collections of objects that don't have a natural ordering , ie there's no obvious specific way in which these object can be ordered, and their class doesn't implement Comparable .另一方面,比较器- 是一个 object,用于为没有自然排序的对象的 collections 提供排序,即没有明显的特定方式可以对这些 object 进行排序,并且它们的 class 没有实施Comparable

Comparators are handy when objects are required to be ordered in differently depending on the situation.当需要根据情况对对象进行不同排序时,比较器很方便。 For instance, you have a class Student , and students can be sorted by their names, ids, grades, etc. And you can create a comparator for each of these cases either by creating a class implementing the interface Comparator and overrides method compare() (like in the code you've listed) or by making use of the static methods like Comparator.comparing() introduced with Java 8.例如,您有一个 class Student ,学生可以按姓名、ID、成绩等进行排序。您可以通过创建一个 class 实现接口Comparator并覆盖方法compare()来为每种情况创建一个比较器(就像在您列出的代码中一样)或通过使用 static 方法,例如 Java 引入的Comparator.comparing() 8。

With that said, interfaces Comparator and Comparable serve the same purpose (to facilitate comparison of object), but have different use cases.话虽如此,接口ComparatorComparable服务于相同的目的(以促进对象的比较),但具有不同的用例。

Caution: don't mix things together by creating a comparator inside the compareTo() method, as it's shown in another answer.注意:不要通过compareTo()方法中创建比较器来将事物混合在一起,如另一个答案所示。 It's a terrible idea.这是个糟糕的主意。 Why?为什么? Because such an implementation will create a new comparator for every invocation of this method.因为这样的实现将为该方法的每次调用创建一个新的比较器 To sort a list of 10.000.000 elements, 10.000.000 * log(10.000.000) comparisons will be required, with each comparison compareTo() will be called and a new instance of comparator will be created.要对包含10.000.000个元素的列表进行排序,需要进行10.000.000 * log(10.000.000)比较,每次比较都将调用compareTo()并创建一个新的比较器实例。 It'll have a negative impact on the application performance because creation of objects is costful, it requires memory allocation and then gives loads of work to the garbage collector.它会对应用程序性能产生负面影响,因为创建对象的成本很高,它需要 memory 分配,然后将大量工作交给垃圾收集器。

Fluent sorting流畅排序

In order to sort a list, you can use static methods sort() from the Collections utility class, that are part of the JDK since the very early version.为了对列表进行排序,您可以使用Collections实用程序 class 中的 static 方法sort() ,它们自早期版本以来就是 JDK 的一部分。 And you could find lots code-snippets on the Inte.net, where Collection.sort() is being used.您可以在 Inte.net 上找到很多代码片段,其中使用了Collection.sort()

With Java 8 method List#sort() was introduced in the List interface and you no longer need to resort to static methods from the Collections class. Instead you can directly invoke method sort() on the list, note that it always expects a comparator as an argument.随着 Java 8 方法List#sort()List接口中引入,您不再需要求助于 Collections class 中的Collections方法。相反,您可以直接调用列表上的方法sort() ,请注意,它始终需要一个比较器作为论据。 If elements of the list implement Comparable you should pass null instead:如果列表的元素实现Comparable你应该传递null而不是:

If the specified comparator is null then all elements in this list must implement the Comparable interface and the elements' natural ordering should be used.如果指定的比较器是null ,则此列表中的所有元素都必须实现Comparable接口,并且应使用元素的自然顺序

myList.sort(null); // only if element of the implement Comparable

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

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