Добавить защитную копию объекта в хешсет

В настоящее время у меня есть этот код:

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; }
}

Если студент меняет имя - как часто это происходит? в вашей системе вам, возможно, вообще не понадобится моделировать ее - или изменить курс, вы просто создаете нового студента и удаляете старого, неправильного.

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