HashSet如何检查重复
当把对象加入HashSet
时,HashSet会先计算对象的hashcode
值来判断对象加入的位置,同时也会与其他加入的对象的hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用equals()
方法来检查hashcode相等的对象是否真的相同。如果两者相同,HashSet就不会让加入操作成功。
咱们举个String类的例子,因为 String类重写了equals(),和hashCode()。
package com.cc;
import java.util.HashSet;
public class HashSetTest {
public static void main(String[] args) {
String str1 = new String("hello");
String str2 = new String("hello");
HashSet hashSet = new HashSet();
hashSet.add(str1);
hashSet.add(str2);
System.out.println(hashSet.size());
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());
System.out.println(hashSet);
}
}
运行结果:
可以看到两个字符串相等,hashCode相同。最终hashSet中只加入了一个元素。
hashCode()与equals()的相关规定:
- 如果两个对象相等,则hashcode一定也是相同的
- 两个对象相等,对两个equals方法返回true
- 两个对象有相同的hashcode值,它们也不一定是相等的
- 综上,equals方法被覆盖过,则hashCode方法也必须被覆盖
- hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。
那咱们自己再来看一个Student例子,没重写equals(),和hashCode()。
package com.cc;
import java.util.HashSet;
public class HashSetTest {
public static void main(String[] args) {
Student student1 = new Student("moon",2);
Student student2 = new Student("moon",2);
HashSet hashSet = new HashSet();
hashSet.add(student1);
hashSet.add(student2);
System.out.println(hashSet.size());
System.out.println(student1.hashCode());
System.out.println(student2.hashCode());
System.out.println(hashSet);
}
}
运行结果:
两个对象的hashCode不同,但是这两个对象是不是完全一样的,可就出现了问题。不符合hashCode()与equals()的规定。
那么你在Student类中重写equals(),和hashCode()这两个方法即可。
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
name.equals(student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
再次运行,发现只插入了一个对象。