Избегайте того же значения в аргументе параметра в объекте - PullRequest
1 голос
/ 23 сентября 2019

Предположим, я создаю объект в Java, как этот

Student std1 = new Student("Tom", "male");

Мне нужно, чтобы другой объект (например, std2, std3 и т. Д.) Имел то же значение, что и std1.Как это сделать?

[править] Пример того, что я хочу:

disallowed: Student std2 = new Student("Tom", "male");

разрешено: Student std2 = new Student("Not Tom", "male"); или Student std2 = new Student("Tom", "female"); или Student std2 = new Student("John", "male"); и т. Д.

Спасибо

Ответы [ 4 ]

0 голосов
/ 23 сентября 2019

Я бы сказал, что вам нужно переопределить методы Student equals и hashCode, а затем проверить в конструкторе, существует ли такой студент.Хороший ответ на этот момент: ссылка

import java.util.*;

public class Student {
    private static final Set<Student> REGISTERED_STUDENTS = new HashSet<>();

    private String name;
    private String gender;

    public static Collection<Student> getRegisteredStudents() {
        return Collections.unmodifiableCollection(REGISTERED_STUDENTS);
    }

    public Student(final String name, final String gender) {
        this.name = name;
        this.gender = gender;

        if (REGISTERED_STUDENTS.contains(this))
            throw DuplicateStudentException();

        REGISTERED_STUDENTS.add(this);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, gender);
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (!(o instanceof Student)) return false;
        final Student student = (Student) o;
        return Objects.equals(name, student.name) && Objects.equals(gender, student.gender);
    }
}

Пожалуйста, обратите внимание, что этот пример не поточно-и использует спорное решение бросать исключения прямо в конструкторе..Возможно, вам понадобится фабричный метод и ConcurrentSkipListSet или другой потокобезопасный набор, например:

class Student {
    private static final Set<Student> REGISTERED_STUDENTS = new ConcurrentSkipListSet<>(Comparator.comparing(Student::getName).thenComparing(Student::getGender));

    private String name;
    private String gender;

    public static Set<Student> getRegisteredStudents() {
        return Collections.unmodifiableSet(REGISTERED_STUDENTS);
    }

    public static void addStudent(final String name, final String gender) {
        Student probablyExists = new Student(name, gender);
        REGISTERED_STUDENTS.add(probablyExists);
    }

    private Student(final String name, final String gender) {
        this.name = name;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public String getGender() {
        return gender;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, gender);
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (!(o instanceof Student)) return false;
        final Student student = (Student) o;
        return Objects.equals(name, student.name) && Objects.equals(gender, student.gender);
    }
}
0 голосов
/ 23 сентября 2019

Предполагая, что под «значением» вы ссылаетесь на имя ученика, я бы предложил вам написать небольшую функцию, которая будет возвращать true, если имя уже занято.Для этого вы можете сохранить всех своих «учеников» в ArrayList:

ArrayList<Student> students = new ArrayList<Student>();

Теперь вы можете добавить учеников в этот ArrayList следующим образом:

private boolean nameIsAlreadyTaken(ArrayList<Student> students, String newName){
    for (int i = 0; i < student.size(); i++){
        if(students.get(i).getName().equals(newName)){
            return true;
        }
    }
    return false;
}

(Вам нужночтобы определить функцию getName () в ученическом классе, чтобы это работало.)

, тогда вы можете сделать что-то вроде этого:

String newName = "Michael";String newGender = "male";

if (!nameIsAlreadyTaken(students, newName)){
students.add(new Student(newName, newGender));
} else{
    //something you want to to if the name is already taken
}

Вы можете сделать это, не передавая ArrayList студентов функции, но это зависит от вас.

0 голосов
/ 23 сентября 2019

Вы можете создать статический String HashSet, добавив объединенное имя, пол к нему.

class YourClass {
   public static Set<String> studentSet = new HashSet<>();

   public static void addStudent(String name, String gender) {
     YourClass.studentSet.add(name + "," + gender);
   }

   public static Boolean studentExists(String name, String gender) {
     return YourClass.studentSet.constains(name + "," + gender);
}

Таким образом, данные в вашем HashSet будут выглядеть как Том, мужчина, Том, женщина, Джон, мужчина.

class Student {
...

public Student(String name, String gender) {
    this.name = name;
    this.gender = gender;
    YourClass.addStudent(name, gender);
  }
}

И при создании экземпляра Student вы можете проверитьHashSet, если в нем нет имени, пола, а затем создать экземпляр и объект.

if(!YourClass.studentExists(name, gender)) {
    Student student = new Student(name, gender);
}

Надеюсь, это решит вашу проблему

0 голосов
/ 23 сентября 2019

Вы можете создать класс, который будет управлять созданием объекта - в основном используйте шаблон flyweight.

Шаг 1. Сделайте конструктор из пакета Student закрытым

public class Student {
    Student(String name, String gender) {
    ...

Шаг 2Внедрить метод equals в Student

   public boolean equals (Object other) {
       if (!(other instanceof Student)) return false;
       Student otherStudent = (Student) other;
       return Objects.equals(otherStudent.getName(), this.getName()) && Objects.equals(otherStudent.getGender(), this.getGender());
   }

Шаг 3. Ввести пул объектов Student в одном пакете

public class StudentPool {
    private List<Student> students = new ArrayList<>();

    public Student getOrCreate(String name, String gender) {
        Student student = new Student(name, gender);
        return students.stream()
                .filter(s -> Objects.equals(s, student))
                .findFirst()
                .orElseGet(() -> {
                    students.add(student);
                    return student;
                });
    }

    public List<Student> get(String name) {
        return students.stream()
                .filter(student -> Objects.equals(student.getName(), name))
                .collect(Collectors.toList());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...