Почему мы используем `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()
метод. Как вы сортируете Student
s? Если вы не говорите Java, как сравнить Student
другому Student
как их заказать? Он может обрабатывать числа (2 меньше 3) и строки ("а" перед "b"), но он не может знать, как сравнить созданный вами пользовательский класс. Поэтому вы должны сообщить об этом - используя compareTo()
метод. призвание sort()
для коллекции объектов, которые не могут быть сравнены, вызовет исключение. призвание sort()
на коллекции Student
закажу их по правилам, которые вы указали в compareTo()
который по name
(обычное сравнение строк).
Что касается самого механизма сортировки, он зависит от реализации, но обычно это комбинация нескольких алгоритмов, гибрид. В Java я верю, что это Timsort
в C# это интроспективный вид. В любом случае, чтобы отсортировать коллекцию подобным образом, вам нужно сравнить элементы, два на два (отсюда и требование реализовать Comparable
). Хитрость заключается в том, как сделать это, чтобы уменьшить количество выполненных сравнений. Существует множество хороших источников, которые объясняют различные методы сортировки, но все сводится к тому, что можно сравнивать элементы и определять, какие из них должны предшествовать, а какие.