猿问

Java Collections.sort() 未按预期排序

我正在尝试按特定属性(“程序”的“学生”对象和“教师”的“教授”对象)对两个不同的对象数组列表进行排序。这两个类都扩展了我的抽象“人”类。


public abstract class Person implements Comparable<Person>{

    private String name;

    private String adress;


    //getters, setters, etc., all works properly


    @Override

    protected Object clone() throws CloneNotSupportedException {

        return super.clone(); 

    }


    public int compareTo(String string) {

        return name.compareTo(string);

    }

}

然后,当我创建一个由 1000000 个随机“人”对象组成的数组时,可以是学生或教授,我决定像这样按他们的名字按字母顺序排序(这可以正常工作)。


Person personByName[] = arrayPersonas.clone();

Arrays.sort(personByName);

然后,我将原始 Person 数组划分为两个 ArrayList,一个用于 Student 对象,另一个用于教授对象:


    ArrayList<Student> studentsByProgram = new ArrayList();

    ArrayList<Professor> professorsByFaculty = new ArrayList();

    for (int i = 0; i < 1000000; i++) { 

        if (arrayPersonas[i] instanceof Student) {

            studentsByProgram.add((Student)arrayPersonas[i]);

        } else {

            professorsByFaculty.add((Professor)arrayPersonas[i]);

        }

    }

当我尝试按我想要的属性按字母顺序对每个 ArrayList 进行排序时,问题就出现了,因为它一直按 Person 的名称对它们进行排序:


Collections.sort(studentsByProgram);

Collections.sort(professorsByFaculty);

在这里,我离开我的学生和教授课程:


public class Student extends Person {

    private String program;

    private int year;

    private double fee;


    //constructor, setters, getters, toString, equals


    @Override

    protected Object clone() throws CloneNotSupportedException {

        return super.clone(); 

    }




    public int compareTo(String string) {

        return program.compareTo(string); 

    }


    @Override

    public int compareTo(Person t) {

        return super.compareTo(t.getName());

    }

}

教授班:


public class Professor extends Person {

    private String faculty;

    private double salary;


    //constructor, setters, getters, toString, equals


    @Override

    protected Object clone() throws CloneNotSupportedException {

        return super.clone(); 

    }



    public int compareTo(String string) {

        return faculty.compareTo(string); 

    }




沧海一幻觉
浏览 203回答 3
3回答

繁花不似锦

您有两个不同的 compareTo() 方法。Collections.sort() 不会调用您期望使用的那个。如果您想使用 Collections.sort() 对学生进行排序,那么您需要一个带有签名的方法 compareTo(Student student);此方法与 compareTo(Person person) “重叠”,这是两个方面的问题:从语义上讲,Person 级别的 compareTo() 方法建立了语义,而 Student 级别的 compareTo() 方法偏离了这些语义,这绝不是一个好主意。从技术上讲,您依赖于与方法绑定相关的实现细节来使您的系统按预期运行。这充其量是狡猾的。我会寻找一种使用显式用户提供的比较器而不是依赖于内部 compareTo() 的排序方法的排序方法。

慕田峪9158850

问题您没有定义Person应该如何比较对象。您错误地定义了如何比较Student和Professor实例。您编写compareTo(String)了具有误导性的重载方法。解决方案Person#compareTo正确定义,删除其compareTo(String):public int compareTo(Person p) {&nbsp; &nbsp; return getName().compareTo(p.getName());}定义Student#compareTo并Professor#compareTo正确删除它们的compareTo(String). 这是一个如何Student#compareTo编写的示例:@Overridepublic int compareTo(Person t) {&nbsp; &nbsp; final int personComparisonResult = super.compareTo(t);&nbsp; &nbsp; if (personComparisonResult == 0) {&nbsp; &nbsp; &nbsp; &nbsp; return program.compareTo(((Student) t).program);&nbsp; &nbsp; }&nbsp; &nbsp; return personComparisonResult;}它说“首先将它们作为Persons进行比较;如果它们相等(此处为同名),则将它们作为Students进行比较(此处为学生的程序)”。我会删除这些方法。对于不适合类域的简单代码行使用单独的方法是不值得的。

POPMUISE

如果要使用与类“自然”排序不同的排序对对象进行排序,则应该使用Arrays.sort(T[], Comparator<T>), 和一个Comparator实现特定排序顺序的对象。该javadoc的用于Comparable解释说,它应该实现的语义。(仔细阅读它们!)关于自然排序:Person[]由compareTo(Person)方法给出的遗嘱的“自然”排序。a&nbsp;Student[](或ArrayList<Student>)的“自然”排序将由该compareTo(Student)方法给出。等等。在这些情况下都compareTo(String)不会使用您的方法!
随时随地看视频慕课网APP

相关分类

Java
我要回答