【问题标题】:Comparator Interface implemented in a nested class在嵌套类中实现的比较器接口
【发布时间】:2014-12-01 22:52:22
【问题描述】:

我是 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));
    }
}

所以它创建了一个新类,仅用于将 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 在此先感谢。

【问题讨论】:

  • 每个编译单元的多个类实际上是 Java 已弃用的特性。你应该总是喜欢嵌套类。
  • 如果您使用单独的Comparator,那么最好将其源代码放在单独的文件中。这不是支持或反对嵌套Comparator 类的论据。很可能是出于方便和清晰的目的,从中提取原始来源的书籍呈现它。

标签: java arrays nested comparator ocpjp


【解决方案1】:

您可以将Comparator 实现为被比较对象的静态嵌套类,如果您可以控制该类(并且如果它是类而不是接口)。但是,根据目标类本身不支持的顺序(无论是通过Comparable 还是通过提供Comparator班级)。在这种情况下,您必须创建自己的独立 Comparator

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

【讨论】:

  • 我所希望的完美答案! :DI 没有考虑你解释的特殊情况,如果我无法访问一个类,我将无法将 Comparator 实现为嵌套类,所以我最好总是将它实现为一个单独的类:)非常感谢(当然还有其他人)!
【解决方案2】:

没有真正的理由不应该真正实现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());
    }
}

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

更多讨论请见here

【讨论】:

  • @Serhiy - 这与使用嵌套类实现 Comparator 的问题有何关系?
  • 当然可以,但在某些情况下您可能需要按学生姓名排序,在其他情况下按他们的 cgpa 排序,当您需要比较方法的两个或多个不同实现时,您无法实现它在需要比较的类中,对吧?但是如果我需要两个不同的实现,我可以简单地创建两个嵌套类,比如 Student.StudentCGPA 和 Student.StudentName
  • compareTo(): To give an idea about sorting the objects to the user of your class, here user who is going to use "Student" class compare() : If the developer didn't provide the compareTo() method to compare or user wants to change the logic to compare two objects of the same class without changing the code of the class itself(Student).
  • @OldCurmudgeon 好吧,也许我的问题与他的问题无关,但是您的回答也与他的问题无关。因为被问到的是:“为什么我不能使用嵌套班级(学生内)?”。而不是“为什么我不应该实现ComprataorComparable?”...
  • @Serhiy for compareTo 你不必编写嵌套类,对吧?有时你只有像“Student”这样的类的.class文件,你不能改变它的源代码,所以你不能写嵌套类,但是是的,如果你有src代码,那么你可以做到,但实际上,你在第一种情况下使用 campare()(即 src 不可用)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-15
  • 2012-09-02
相关资源
最近更新 更多