如果你看过 HashSet 源码的话就应该知道:HashSet 底层就是基于 HashMap 实现的。(HashSet 的源码非常非常少,因为除了 clone()、writeObject()、readObject()是 HashSet 自己不得不实现之外,其他方法都是直接调用 HashMap 中的方法。
| HashMap | HashSet |
|---|---|
| 实现了 Map 接口 | 实现 Set 接口 |
| 存储键值对 | 仅存储对象 |
| 调用 put()向 map 中添加元素 | 调用 add()方法向 Set 中添加元素 |
| HashMap 使用键(Key)计算 hashcode | HashSet 使用成员对象来计算 hashcode 值,对于两个对象来说 hashcode 可能相同,所以 equals()方法用来判断对象的相等性 |
以下内容摘《Head first java》第二版:
当你把对象加入HashSet时,HashSet 会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他加入的对象的 hashcode 值作比较,如果没有相符的 hashcode,HashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让加入操作成功。
hashCode()与 equals() 的相关规定:
hashCode() 的默认⾏为是对堆上的对象产⽣独特值。如果没有重写 hashCode() ,即使通过 equals() 判断为相同的两个对象,在加入 HashSet 时,也不会被 HashSet 认为是重复对象。
import java.util.HashSet;
public class People {
String idCard;
public People(String idCard) {
this.idCard = idCard;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
People people = (People) o;
return idCard.equals(people.idCard);
}
public static void main(String[] args) {
People a = new People("a");
People a1 = new People("a");
// output: true
System.out.println(a.equals(a1));
HashSet<People> set = new HashSet<>();
set.add(a);
set.add(a1);
// output: 2
System.out.println(set.size());
}
}