I'm trying to avoid adding duplicated (student) objects in an ArrayList... I tried to loop over the array and check the ID and PhoneNO but using these two conditions I'm not able to add any object even if it's unique... Also, I tried to check using the contains() function but it's not working, it allows adding duplicated objects, how can I solve it?
public void addStudent(Student newStudent) {
//1-Looping over the ArrayList<student> and check their ID and PhoneNO (can't add any object of student)
for(Student student:students) {
if(newStudent.getId() == student.getId() || newStudent.getPhoneNumbre() == student.getPhoneNumbre()) {
System.out.println("Error");
break;
}else
this.students.add(newStudent);
}
//2- validate using the contains(), but it allows duplicated Objects
if (!this.students.contains(newStudent))
this.students.add(newStudent);
}
CodePudding user response:
For two distinct object instances, the ==
operator will always return false
, even if these two instances are equal.
In Java, the ==
operator tests for identity, not for equality (although, if two things are identical, they are obviously also equal).
The nasty thing is that in Java two apparently distinct Strings with the same contents can be equal and identical – but this depends on the underlying JVM and other conditions. Meaning, you should not rely on this!
So if Student::getId
and Student::getPhoneNumbre
do return object references and not Primitives, you need to compare them with Object::equals
:
if( newStudent.getId().equals( student.getId() )
|| newStudent.getPhoneNumbre().equals( student.getPhoneNumbre() ) ) …
I assume you are aware that your logic identifies a new student as a duplicate of an existing one when at least id or phone number are equals.
Otherwise, when a duplicate requires that both be equal, you should consider to implement the method Object::equals
for the class Student
; that would simplify the check:
if( newStudent.equals( student ) ) …
An implementation for equals()
may look like this:
@Override
public final boolean equals( Object o )
{
final var retValue = (this == o)
|| (o instanceof Student other
&& Objects.equals( getId(), other.getId() )
&& Objects.equals( getPhoneNumbre(), other.getPhoneNumbre() ));
return retValue;
}
Keep in mind that it is strongly recommended that you always implement also Object::hashCode
when you implement Object::equals
and vice versa – even when you currently need only one of the methods!
Oh, and in your original code, you need to assure that Student::getId
and Student::getPhoneNumbre
will not return null
; my suggested implementation of equals()
does already take care of that.
If you are not stuck to an implementation of List
to store the Student
instance, you should consider to use an implementation of Set
instead: that does the duplicate check automatically on insertion, once you provided Student.equals()
and Student.hashCode()
.
You can even use a Set
implementation if duplicates are identified by either the id or the phone number, but that would be a bit nasty (although it works perfectly):
Set<Student> students = new TreeSet( (s1,s2) -> Comparator.naturalOrder.compare( s1.getId(), s2.getId() ) * Comparator.naturalOrder.compare( s1.getPhoneNumbre(), s2.getPhoneNumbre() ) );
…
if( !students.add( newStudent ) ) out.println( "Duplicate!" )
Confessed, the output order will be strange, but this can be easily fixed …
The implementation of the Comparator
here assumes that id and phone number will implement Comparable
.
Finally, List::contains
does not work for you because it requires that you implemented Student::equals
properly. If you have not overridden that method, contains()
checks for identity, not equality.
CodePudding user response:
Try using set(allows no duplicates) as given below:
Set<Student> student = new HashSet<>();
student.add(new Student());
then convert the set to list, which now will have distinct student records
List<Student> studentList= new ArrayList<>(student);
CodePudding user response:
My guess is that your Student Class is missing equals() and hashCode() methods.
Implement equals() and hashCode() methods in the Student Class. You can also auto-generate the equals() and hashCode() methods if you are using an IDE like Eclipse or IntelliJ.
Also, instead of ArrayList, use HashSet. HashSet will prevent insertion of duplicates because a set only contains unique objects. If you must use ArrayList, then having the equals() is important for the contains() method of ArrayList to work properly. Also, a side note, if the two Student objects are equal then their hashCode must be the same.