[英]How can I avoid adding duplicated objects in an ArrayList?
我试图避免在 ArrayList 中添加重复的(学生)对象......我试图遍历数组并检查 ID 和 PhoneNO 但是使用这两个条件我无法添加任何 object 即使它是唯一的。 .. 另外,我尝试使用 contains() function 进行检查,但它不起作用,它允许添加重复的对象,我该如何解决?
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);
}
我的猜测是您的 Student Class 缺少 equals() 和 hashCode() 方法。
在 Student Class 中实现 equals() 和 hashCode() 方法。如果您使用 IDE,例如 Eclipse 或 IntelliJ,您也可以自动生成 equals() 和 hashCode() 方法。
此外,使用 HashSet 而不是 ArrayList。 HashSet 将防止插入重复项,因为一个集合只包含唯一的对象。 如果您必须使用 ArrayList,那么拥有 equals() 对于 ArrayList 的 contains() 方法正常工作很重要。 另外,请注意,如果两个 Student 对象相等,则它们的 hashCode 必须相同。
对于两个不同的 object 实例, ==
运算符将始终返回false
,即使这两个实例相等。
在 Java 中, ==
运算符测试同一性,而不是相等性(尽管如果两个事物相同,它们显然也相等)。
令人讨厌的是,在 Java 中,两个具有相同内容的明显不同的字符串可以相等且相同——但这取决于底层 JVM 和其他条件。 意思是,你不应该依赖这个!
因此,如果Student::getId
和Student::getPhoneNumbre
确实返回 object 引用而不是基元,则需要将它们与Object::equals
进行比较:
if( newStudent.getId().equals( student.getId() )
|| newStudent.getPhoneNumbre().equals( student.getPhoneNumbre() ) ) …
我假设您知道当至少 id或电话号码相等时,您的逻辑将新学生识别为现有学生的副本。
否则,当副本要求两者相等时,您应该考虑为 class Student
实现方法Object::equals
; 这将简化检查:
if( newStudent.equals( student ) ) …
equals()
的实现可能如下所示:
@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;
}
请记住,强烈建议您在实现Object::equals
::equals 时始终同时实现Object::hashCode
,反之亦然——即使您目前只需要其中一种方法!
哦,在您的原始代码中,您需要确保Student::getId
和Student::getPhoneNumbre
不会返回null
; 我建议的equals()
实现已经解决了这个问题。
如果您不坚持使用List
的实现来存储Student
实例,则应该考虑使用Set
的实现:一旦您提供了Student.equals()
和Student.hashCode()
,它就会在插入时自动进行重复检查.
如果通过 id 或电话号码识别重复项,您甚至可以使用Set
实现,但这有点令人讨厌(尽管它工作得很好):
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!" )
承认,output 的顺序会很奇怪,但这很容易修复……
此处Comparator
的实现假定 id 和电话号码将实现Comparable
。
最后, List::contains
对您不起作用,因为它要求您正确实施Student::equals
。 如果您没有覆盖该方法,则contains()
检查身份,而不是相等性。
尝试使用 set(allows no duplicates),如下所示:
Set<Student> student = new HashSet<>();
student.add(new Student());
然后将集合转换为列表,现在将具有不同的学生记录
List<Student> studentList= new ArrayList<>(student);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.