Supposons que je crée un objet en Java comme celui-ci
Student std1 = new Student("Tom", "male");
Je dois empêcher qu'un autre objet (tel: std2, std3, etc.) ait la même valeur que std1. Comment faire?
[modifier] L'exemple de ce que je veux est:
interdit: Student std2 = new Student ("Tom "," male ");
autorisé: Student std2 = new Student (" Not Tom "," male ");
ou Student std2 = new Student ("Tom", "female");
ou Student std2 = new Student ("John", "male");
, etc p>
Merci
4 Réponses :
Vous pouvez créer une classe qui contrôlera la création de l'objet - utilisez essentiellement un modèle de poids mouche.
Étape 1. Rendez le constructeur du package Student-private
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()); } }
Étape 2. Implémentation de la méthode equals dans 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()); }
Étape 3. Implémentation d'un pool d'objets Student dans le même package
public class Student { Student(String name, String gender) { ...
Étant donné que l'OP veut que la combinaison nom + sexe soit unique (pas seulement le nom), vous devez créer une clé combinant ces deux valeurs plutôt que d'utiliser le nom comme clé
En supposant que par "valeur" vous faites référence au nom des élèves, je vous suggère d'écrire une petite fonction qui retournera vrai si le nom est déjà pris. Pour ce faire, vous pouvez stocker tous vos "étudiants" dans une ArrayList:
if (!nameIsAlreadyTaken(students, newName)){ students.add(new Student(newName, newGender)); } else{ //something you want to to if the name is already taken }
Vous pouvez maintenant ajouter des étudiants à cette ArrayList comme suit:
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; }
Vous pouvez créer un String HashSet statique en y ajoutant un nom concaténé, un sexe.
if(!YourClass.studentExists(name, gender)) { Student student = new Student(name, gender); }
Ainsi, les données de votre HashSet ressembleront à Tom, homme, Tom, femme, John, homme.
class Student { ... public Student(String name, String gender) { this.name = name; this.gender = gender; YourClass.addStudent(name, gender); } }
Et pendant la création une instance de Student, vous pouvez vérifier le HashSet si celui-ci ne contient pas de nom, de sexe, puis d'instancier et d'objet.
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); }
J'espère que cela résout votre problème
Je dirais que vous devez remplacer les méthodes equals
et hashCode
de Student
, puis vérifier dans le constructeur si un tel étudiant existe . Bonne réponse sur ce point: lien .
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); } }
Veuillez noter que cet exemple est n'est pas thread-safe et utilise une solution discutable consistant à lancer une exception directement dans le constructeur. Vous voudrez probablement une méthode d'usine et ConcurrentSkipListSet
ou une autre collection thread-safe, comme ceci:
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); } }
Non, vous n'avez pas besoin de cela / devriez le faire. Ce que vous voudrez peut-être, c'est interdire à une deuxième instance
Student
avec les mêmes données d'être persistante ou ajoutée à unCourse
ou autre chose, mais vous devriez pas interdire la création de l’objet lui-même.nouvel étudiant ("Tom", "femme")
ounouvel étudiant ("pas Tom", "homme")
est-il autorisé? Ce que vous entendez par "la même valeur" n'est pas clair ...Je pense que vous avez besoin d'un identifiant intégré. Si vous essayez de créer un objet avec des valeurs en double, cela ne sera pas autorisé.
Vous pouvez créer un String HashSet statique en y ajoutant un nom concaténé, un sexe. Ainsi, les données de votre HashSet ressembleront à
Tom, homme
,Tom, femme
,John, homme
. Et dans le constructeur paramétré de votre classe Student, vous pouvez vérifier le HashSet s'il ne contient pas de nom, de sexe, puis instancier et objet. Quelque chose comme ca!