Почему мы используем `this` в CompareTo в сопоставимых реализациях?

Я немного новичок в Java и очень плохо знаком с фреймворком Коллекции. я знаю это this ссылается на текущий объект

public class Student implements Comparable <Student> {

    String name;
    int grade;

    public Student(String name, int grade) {
        this.name = name;
        this.grade = grade;
    }
    public int compareTo(Student s) {
         return this.name.compareTo(s.name);
    }
    public String toString() {
        return this.name + ", " + this.grade;
    }
}

Вот this.name является нулевым и s.name действительно имеет значение, так что мы пытаемся сделать, сравнивая this.name.compareTo(s.name);

И что на самом деле происходит, когда мы делаем Collections.sort(studentList);?

Фрагмент кода только для демонстрационных целей

2 ответа

Решение

Вы задаете два разных вопроса, поэтому я отвечу на них отдельно

Первое, что мы пытаемся сравнить, сравнивая this.name.compareTo(s.name);

Когда метод CompareTo вызывается для объекта класса Student, он становится вызывающим объектом. Поскольку вызывающий объект (надеюсь) был правильно инициализирован, this.name будет именем вызывающего объекта.

s.name - это имя объекта Student, переданного в метод CompareTo, который снова (будем надеяться) правильно инициализируется и имеет имя.

То, что сводится к тому, является переменной String, вызывающей CompareTo, передавая переменную String для сравнения с

Второе - это то, что действительно происходит, когда мы делаем Collections.sort(studentList);

Вот JavaDocs для метода Collections.Sort, но вы, вероятно, спрашиваете, что он делает по отношению к вашей реализации Comparable. Короче говоря, он использует ваш метод CompareTo при сравнении для сортировки

Поскольку кажется, что name является важным свойством Student Первое, что вы должны спросить себя: "Какое действительное имя для студента?" Является null действует? Допустима ли пустая строка? Если нет, необходимо предотвратить инициализацию Student с недействительным name с помощью установщика:

public void setName(String name) {
  if (name is invalid) {
    throw error;
  }

  this.name = name; // name is valid, so this is safe now
}

Теперь вызовите сеттер в вашем конструкторе, и вы будете уверены, что если у вас есть Studentу него будет действительный name,

Одна проблема с недействительным name что если не помешать null значения, которые вы получите NullPointerException каждый раз, когда вы звоните compareTo() метод. Вы по существу будете звонить null.compareTo() и, очевидно, null У него нет такого метода, у него нет никаких методов.

Теперь, чтобы sort() метод. Как вы сортируете Students? Если вы не говорите Java, как сравнить Student другому Studentкак их заказать? Он может обрабатывать числа (2 меньше 3) и строки ("а" перед "b"), но он не может знать, как сравнить созданный вами пользовательский класс. Поэтому вы должны сообщить об этом - используя compareTo() метод. призвание sort() для коллекции объектов, которые не могут быть сравнены, вызовет исключение. призвание sort() на коллекции Student закажу их по правилам, которые вы указали в compareTo() который по name (обычное сравнение строк).

Что касается самого механизма сортировки, он зависит от реализации, но обычно это комбинация нескольких алгоритмов, гибрид. В Java я верю, что это Timsortв C# это интроспективный вид. В любом случае, чтобы отсортировать коллекцию подобным образом, вам нужно сравнить элементы, два на два (отсюда и требование реализовать Comparable). Хитрость заключается в том, как сделать это, чтобы уменьшить количество выполненных сравнений. Существует множество хороших источников, которые объясняют различные методы сортировки, но все сводится к тому, что можно сравнивать элементы и определять, какие из них должны предшествовать, а какие.

Другие вопросы по тегам