HashSet集合的基本使用
HashSet(散列存放的子类)
无序: 跟放入的顺序无关,结果也是无序的
元素不允许重复
跟TreeSet不同 尽管没有实现比较器 也不会报错 但是没有实现查重规则,所以HashSet的查重规则(因为没有大小比较)所以不是比较器
那么HashSet的查重规则是什么呢?
先调用HashCode方法在调用equals方法进行比较
- HashSet集合在放入引用数据类型时需要进行查重比较 查重规则是:
先调用HashCode方法,如果相等则再去调用equals方法进行各项属性的比较;如果HashCode方法不相等则判定两个对象不相等。
具体的操作步骤:
- 第一步:
HashCode方法:
什么是HashCode方法?
在Object类中定义的,默认的功能是返回当前对象跟地址值相关的一串数据(无意义)
那么需要我们自己覆写实现什么样的有意义的功能呢?
为什么HashSet集合在放入对象时需要先比较HashCode方法再去比较equals方法呢?为什么不能直接调用equals方法呢?
equals方法是对象和对象之间进行各项属性的比较 从而判断两个对象是否相等,所以效率非常地下,所以需要先调用HashCode方法进行非常效率的的比较,也就是先快速比较两个对象是否相等,一旦HashCode方法比较出两个对象不相等了,就不再需要去比较equals,提高了效率;如果HashCode无法判断出这两个对象是否相等那就需要equals来判断各项属性是否相等。
HashCode方法到底该如何写呢?应该实现什么样的功能?
实现根据各项属性动态计算出一个哈希码,先进行每一个对象的哈希码比较,一旦HashCode返回值也就是哈希码不相等那么两个对象必然不相等,那么比较出结果不需要再调用equals方法;如果HashCode返回值也就是哈希码相等并不能说明两个对象一定相等,因为不同的数值经过相同的算法可能计算出相同的结果,所以这个时候就需要用到equals方法进行各项属性的比较看看每个属性是否都相等。
哈希码的计算方法例如:age5+name.length3 - 第二步:
equals方法:
就是进行各项属性的详细比较。
先比较HashCode方法是为了提高比较效率,后用equals方法比较是为了提高比较的准确率。
那么我们如果不覆写这两个方法HashCode不会报错,但是也没有实现查重为什么?
因为如果我们没有覆写,那么调用的是父类的Object的hashCode方法,而Object的HashCode方法返回值是地址值,只要是新创建出来的对象地址必然不相等而我们想要比较的是属性值是否相等所以需要覆写。如果地址相等了HashCode还会去调用equals方法,那么此时我们依然没覆写,调用的是Object类的equals进行 == 比较 比较地址。所以我们必须进行两个方法的合理覆写,定义我们想要的比较方法。
public class Demo {
public static void main3(String[] args) {
Person person = new Person();
System.out.println(person.hashCode());//381259350
}
public static void main(String[] args) {
HashSet<Person> set = new HashSet<>();
set.add(new Person