Добавить защитную копию объекта в хешсет
В настоящее время у меня есть этот код:
public final class Tutor {
private String name;
private final Set<Student> tutees;
public Tutor(String name, Student[] students){
this.name = name;
tutees = new HashSet<Student>();
for (int i = 0; i<students.length; i++)
tutees.add(students[i]);
}
Я пытаюсь переписать его (просто на бумаге), чтобы он делал / добавляет защитные копии студентов, а не добавлял их непосредственно в хэш-набор, и мне интересно, будет ли следующий код делать это:
public final class Tutor {
private String name;
private final Set<Student> tutees;
public Tutor(String name, Student[] students){
this.name = name;
tutees = new HashSet<Student>();
for (int i = 0; i<students.length; i++)
tutees.add(students[i](students.getName(), students.getCourse());
}
Код для студента, если это необходимо:
public class Student {
private String name;
private String course;
public Student(String name, String course){
this.name = name;
this.course = course;
}
public String getName() { return name; }
public String getCourse() { return course; }
public void setName(String name) {
this.name = name;
}
public void setCourse(String course){
this.course = course;
}
}
Спасибо
2 ответа
Вы делаете это правильно, но с некоторыми ошибками, поскольку вы пишете это на бумаге. Если переписать его в программу, он не скомпилируется из-за этой строки
tutees.add(students[i](students.getName(), students.getCourse());
которые должны быть заменены
tutees.add(new Student(students[i].getName(), students[i].getCourse());
Обратите внимание, вы добавляете новый Student
, но поля инициализируются существующими ссылками, что приводит к мелкому копированию - объекты различны, но совместно используют содержимое. Тем не мение, String
класс immutable
Это означает, что каждый метод, который изменяет строку, создает новую строку с примененными изменениями, а старый остается неизменным. Таким образом, даже если оригинальный ученик и его копия разделяют содержимое, модификации строк не могут влиять друг на друга, поэтому мы можем сказать, что это нечто вроде защитной копии.
Student original = new Student("name", "course");
Student copy = new Student(original.getName(), original.getCourse());
// does not change the name of the copy
String modifiedName = copy.getName().replaceAll("a", "b");
Вот пример истинного защитного копирования (глубокого копирования):
Student deepCopy = new Student(
new String(original.getName()),
new String(original.getCourse())
);
По соображениям эффективности, если вы знаете, что работаете с классами, которые immutable
Скопируйте их ссылки.
Вы определили проблему, заключающуюся в том, чтобы Set
плохая идея Вы не хотите что-то менять, когда оно входит в набор, потому что это нарушает контракт набора.
Создание копии лечит симптомы, но не относится к основной проблеме. Проблема в том, что ваш ученический класс изменчив. Если вы сделаете свой ученический класс неизменяемым, вам не нужно беспокоиться о копировании, и это будет значительно менее подвержено ошибкам.
public class Student {
private String name;
private String course;
public Student(String name, String course){
this.name = name;
this.course = course;
}
public String getName() { return name; }
public String getCourse() { return course; }
}
Если студент меняет имя - как часто это происходит? в вашей системе вам, возможно, вообще не понадобится моделировать ее - или изменить курс, вы просто создаете нового студента и удаляете старого, неправильного.