4

我是 stackoverflow.com 的新手,但我经常在遇到问题时使用它来搜索答案,但现在我找不到任何搜索我的问题的结果,所以我在这里问:) 我正在为OCPJP SE 7 认证,考试 1Z0-804,我正在使用一本书(只有一本可用的 afaik,Ganesh\Sharma's one)和 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));
    }
}

所以它创建了一个新类,仅用于将 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));
    }
}

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

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

请帮助 :D 在此先感谢。

4

2 回答 2

6

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

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

于 2014-10-07T14:01:00.353 回答
-2

没有真正的理由不应该同时实现 Comparableand Comparator

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());
    }
}

然而,通常更合适的是只实现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);
        }
    });
}

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

于 2014-10-07T13:36:44.587 回答