java 在嵌套类中实现的比较器接口

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26237242/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 09:32:36  来源:igfitidea点击:

Comparator Interface implemented in a nested class

javaarraysnestedcomparatorocpjp

提问by RaffoSorr

I'm new on stackoverflow.com but I often used it to search for answers whenever I had a problem, but now I can't find any result searching for my problem so I'm asking here :) I'm studying for the OCPJP SE 7 certification, exam 1Z0-804, and I'm using a book (there is only one available afaik, Ganesh\Sharma's one) In the collections chapter, about the Comparator interface, the book provide this example of using both the Comparator and the Comparable interface to sort an array of Student elements, but the question is about the Comparator:

我是 stackoverflow.com 的新手,但我经常在遇到问题时用它来搜索答案,但现在我找不到任何搜索我的问题的结果,所以我在这里问:) 我正在学习OCPJP SE 7 认证,考试 1Z0-804,我正在使用一本书(只有一个可用的 afaik,Ganesh\Sharma 的一个)在集合章节中,关于 Comparator 接口,这本书提供了使用两个 Comparator 的示例和 Comparable 接口对 Student 元素数组进行排序,但问题是关于 Comparator:

import java.util.*;

class Student implements Comparable<Student> {
    private String id, name;
    private Double cgpa;
    public String getName() {
        return name;
    }
    public String getId() {
        return id;
    }
    public Double getCgpa() {
        return cgpa;
    }
    public Student(String studentId, String studentName, double studentCGPA) {
        id=studentId;
        name=studentName;
        cgpa=studentCGPA;
    }
    public String toString() {
        return id+" "+name+" "+cgpa;
    }
    public int compareTo(Student that) {
        return this.id.compareTo(that.id);
    }
}

class StudentCGPA implements Comparator<Student> {
    public int compare(Student s1, Student s2) {
        return s1.getCgpa().compareTo(s2.getCgpa());
    }
}

class MyMainClass {
    public static void main(String[] args) {
        Student[] students =    {   new Student("cs011", "Lennon", 3.1),
                                    new Student("cs021", "McCartney", 3.4),
                                    new Student("cs012", "Harrison", 2.7),
                                    new Student("cs022", "Starr", 3.7),
                                };
        Arrays.sort(students, new StudentCGPA());
        System.out.println(Arrays.toString(students));
    }
}

So it creates a new class only for using the Comparator interface with two Student objects, but I think this is very uncomfortable so I wonder: why can't I use a nested class (within Student)? Like this:

所以它创建了一个新类,仅用于将 Comparator 接口与两个 Student 对象一起使用,但我认为这很不舒服所以我想知道:为什么我不能使用嵌套类(在 Student 中)?像这样:

import java.util.*;

class Student implements Comparable<Student> {
    private String id, name;
    private Double cgpa;
    public String getName() {
        return name;
    }
    public String getId() {
        return id;
    }
    public Double getCgpa() {
        return cgpa;
    }
    public Student(String studentId, String studentName, double studentCGPA) {
        id=studentId;
        name=studentName;
        cgpa=studentCGPA;
    }
    public String toString() {
        return id+" "+name+" "+cgpa;
    }
    public int compareTo(Student that) {
        return this.id.compareTo(that.id);
    }
    static class StudentCGPA implements Comparator<Student> {
        public int compare(Student s1, Student s2) {
            return s1.getCgpa().compareTo(s2.getCgpa());
        }
    }
}

class MyMainClass {
    public static void main(String[] args) {
        Student[] students =    {   new Student("cs011", "Lennon", 3.1),
                                    new Student("cs021", "McCartney", 3.4),
                                    new Student("cs012", "Harrison", 2.7),
                                    new Student("cs022", "Starr", 3.7),
                                };
        Arrays.sort(students, new Student.StudentCGPA());
        System.out.println(Arrays.toString(students));
    }
}

The book says nothing about using nested classes instead of normal ones, but I can't see why it should be bad to do like this... Is there any problem with my code (the 2nd one)? Should I follow what the book says because my implementation of Comparator is wrong? (Note: the code compiles and runs without problem, with the expected output in both cases)

这本书没有提到使用嵌套类而不是普通类,但我不明白为什么这样做会很糟糕……我的代码(第二个)有什么问题吗?我是否应该遵循书中所说的,因为我对 Comparator 的实现是错误的?(注意:代码编译和运行没有问题,在两种情况下都具有预期的输出)

[cs012 Harrison 2.7, cs011 Lennon 3.1, cs021 McCartney 3.4, cs022 Starr 3.7]

Please help :D Thanks in advance.

请帮助 :D 提前致谢。

回答by John Bollinger

You can implement a Comparatoras a static nested class of the one being compared, ifyou are in control of that class (and if it is a class rather than an interface). It is not at all uncommon, however, that you want to compare instances of a class that you do not control, according to an order that the target class does not support natively (whether by being Comparableor by providing a Comparatorclass). In that case you must create your own, separate Comparator.

如果您控制该类(并且它是一个类而不是接口)Comparator可以将a实现为所比较对象的静态嵌套类。然而,根据目标类本身不支持的顺序(无论是通过存在Comparable还是通过提供Comparator类)来比较不受控制的类的实例,这种情况并不少见。在这种情况下,您必须创建自己的、单独的Comparator.

Even when you control everything, it is somewhat a matter of taste whether to implement Comparators as top-level classes. I'm not sure why you call it "uncomfortable"; myself, I usually prefer to avoid nested classes when I can. Note, too, that whether you nest or not, the Comparatorimplementation class will be compiled to a separate class file.

即使你控制了一切,是否将Comparators实现为顶级类也有点品味问题。我不知道你为什么称之为“不舒服”;我自己,我通常更喜欢尽可能避免嵌套类。还要注意,无论是否嵌套,Comparator实现类都将被编译为单独的类文件。

回答by OldCurmudgeon

There's no real reason why you shouldn't actually implement bothComparableand Comparator.

还有就是为什么你不能真正实现没有真正的理由ComparableComparator

class Student implements Comparable<Student>, Comparator<Student> {

    private final String id;
    private final String name;
    private final Double cgpa;

    public String getName() {
        return name;
    }

    public String getId() {
        return id;
    }

    public Double getCgpa() {
        return cgpa;
    }

    public Student(String studentId, String studentName, double studentCGPA) {
        id = studentId;
        name = studentName;
        cgpa = studentCGPA;
    }

    @Override
    public String toString() {
        return id + " " + name + " " + cgpa;
    }

    @Override
    public int compareTo(Student that) {
        return this.id.compareTo(that.id);
    }

    @Override
    public int compare(Student o1, Student o2) {
        return o1.getCgpa().compareTo(o2.getCgpa());
    }
}

It is often more appropriate, however, to implement only Comparableand use other methods (such as inner classes or anonymous classes) to choose different orders.

然而,通常更合适的是只实现Comparable并使用其他方法(例如内部类或匿名类)来选择不同的顺序。

    class ByCgpa implements Comparator<Student> {

        @Override
        public int compare(Student o1, Student o2) {
            return o1.getCgpa().compareTo(o2.getCgpa());
        }

    }

    Collections.sort(list, new ByCgpa());

static void sortByCgpaAndName(Collection<Student> students) {
    Collections.sort(students, new Comparator<Student> () {

        @Override
        public int compare(Student o1, Student o2) {
            int byCgpa = o1.getCgpa().compareTo(o2.getCgpa());
            return byCgpa != 0 ? byCgpa : o1.name.compareTo(o2.name);
        }
    });
}

See herefor further discussion.

请参阅此处进行进一步讨论。