HashSet是无重复的集合,那么问题就是如何判定一个元素是否和另一个元素是相等的。这里需要自定义相等性。当有对象加入HashSet时,首先java会通过对象的hashcode值来判断对象加入的位置及是否有重复的hashcode。如果没有重复的hashcode就认为没有相同的对象。如果有重复的hashcode,会再调用equals()方法判断有重复hashcode的两个对象是否真的相等。如果相等那么HashSet就知道要加入的项目已经重复了,加入的操作就不会发生。相等性有两个层次
- 引用相等性: 如果只认为引用指向同一个对象才算相等,那么什么都不用做。对引用调用hashCode()会返回引用指向的对象特有的序号(大部分是对对象在堆上的地址的映射,因此不会有重复的序号。但也有像String一样的其实是字面值的映射)
- 对象相等性:如果实际需要把不同的对象视为相等的,需要覆盖从Object继承下来的hashCode()才能确保两个对象有相同的hashcode,然后需要覆盖equals()方法。之所以需要有equals()方法是因为hashcode相同的对象未必相同,hashCode()所使用的杂凑算法可能会凑巧让多个对象返回相同的杂凑值,但这种情况也比较少,所以equals其实很少会被调用。