hashcode()和equals()在hashset中的应用---

hashcode()和equals()的默认实现

  • 首先hashcode()方法和equal()方法都可以用来对比两个对象是否相等一致。
  • 在默认情况下,使用equals方法比较两个元素比较的是两个对象的地址与==等价。对于string类对象它重写了equals方法所以比较的是字符串的内容。
  • hashCode()方法返回的就是一个数值表示的hash码。默认情况下,不同对象的哈希码是不同的。

equals()方法的覆写

  • 我们已经知道了,默认情况下equals()方法等价于==,它只能判断两个对象的引用地址是否相同,无法判断两个对象的内容是否相同。
  • 一般情况下,我们都会对自定义类的equals方法进行覆写,从而判断两个对象的内容是否相同。
  • 具体的覆写方法如下:首先判断传入的对象是否为空,然后判断两个对象引用地址是否相同,再判断两个对象的类型是否一致,最后判断两个对象各个域的内容是否一样。

hashcode方法的重写

  • 一般在将对象做为元素存储到HashSet集合中时,必须要对equals和HashSet进行重写。

HashSet保证元素唯一性的原理

  • 通常如果要保证序列的唯一性,在添加元素的时候要和序列中已经存在的元素一一对比,如果不重复再进行添加,如果重复就不添加了。但是如果序列的元素过多这种方法效率就会十分低下。
  • 而HashSet底层是这样实现的:首先HashSet的底层是一个数组加链表组成的散列表,每个数组元素存储一个链表的头节点。
  • 在HashSet中新添加一个元素时,先根据元素的hash值计算一个下标值,然后判断该下标处是否已经存储元素,如果不存在就直接存储,如果存在就和已经存在的元素一一比较它们的hash值。如果新元素的hash值和该下标处所有元素的下标值都不同,就在对应链表中存储新元素,否则使用equals比较元素的内容是否相同,如果不同就存储新元素,如果相同就说明元素重复,不进行添加。

hashcode方法在HashSet集合中的使用

  • 通过以上说明,我们已经明白了HashSet如何保持元素不重复了。
  • 现在我们使用HashSet存储一下字符串试试:
 HashSet<String> h = new HashSet<>();
        h.add("张三");
        h.add("李四");
        h.add("王大锤");
        h.add("张三");

        for(String s:h){
            System.out.println(s);
        }
  • 我们使用HashSet存储了四个字符串,其中两个重复,最后我们发现重复的元素不见了,说明HashSet保证了元素的唯一性。
  • 现在让我们存储自定义的实例对象试试看。
HashSet<Student> set = new HashSet<>();
       set.add(new Student("张三",18));
       set.add(new Student("李四",15));
       set.add(new Student("王大锤",15));
       set.add(new Student("张三",18));

       for(Student s:set){
           System.out.println(s.name+"--"+s.age);
       }
 class Student{
    public String name;
    public int age;
    Student(String name,int age){
        this.name = name;
        this.age = age;
    }
}
  • 以上代码我们定义了一个学生类,并实例化了四个学生对象进行存储,其中两个学生是重复的。可是最后我们发现四个对象都存储了,HashSet中有两个张三,这是为什么呢?
  • 因为我们没有重写hashcode和equals方法,这时候第一个对象和第四个对象的hash值和地址都是不相同的,因为地址不相同所以程序认为这两个对象不相同。
  • 这时候当存储第四个对象的时候,系统先判断它的hash值,发现它的hash值和已经存在的三个元素的hash值不同,所以就会直接存储。
  • 所以在重写hashcode方法时必须要保证第一个元素与第四个元素的hash值相同。为了简单起见我们重写hashcode时直接return 1,equals方法比较对象各成员是否相等。
class Student{
    public String name;
    public int age;
    Student(String name,int age){
        this.name = name;
        this.age = age;
    }
    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 &&
                Objects.equals(name, student.name);
    }
    public int hashCode() {
        return 1;
    }
}
  • 重写了两个方法后我们发现元素不重复了,但是还有一个问题,在存储元素时四个对象的hash都一样,它们的存储位置都一样,说明所有元素都堆积到了一个下标,空间利用率极低。所以我们重写hashCode方法时既要保证相同元素的hash值相同,也要保证不同元素的hash值尽可能不同,这样才能保证元素在散列表存储时尽可能分散。
  • 系统自动生成的hashcode方法是这样的
public int hashCode() {
        return Objects.hash(name, age);
    }

总结

  • 在覆写equals方法前,它比较的是两个对象的地址(strings除外),覆写之后可以用来比较两个对象内容是否一样。
  • hashcode方法只有在set集合中用到。
  • 重写的hashcode方法的特点:两个元素hash值不同,元素一定不相同,两个元素的hash值相同,元素可能不相同。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用HashSet时,如果要将自定义对象作为元素存储在其,则需要重写该对象的hashCode()和equals()方法。 hashCode()方法用于确定元素的哈希值,用于在HashSet确定元素的位置。 equals()方法用于比较两个元素是否相等。如果两个元素的hashCode()值相同,则会调用equals()方法来确定它们是否相等。 重写这两个方法的规则如下: - hashCode()方法: 1. 在同一对象多次调用hashCode()应该返回相同的整数。 2. 如果equals()比较两个对象相等,则它们的hashCode()返回值应该相同。 3. hashCode()返回值不一定唯一,不同对象可能会返回相同的整数。 - equals()方法: 1. 自反性: 对于任何非空引用x,x.equals(x)应该返回true。 2. 对称性: 对于任何非空引用x和y,当且仅当y.equals(x)返回true时,x.equals(y)也应该返回true。 3. 传递性: 对于任何非空引用x,y,z,如果x.equals(y)返回true,并且y.equals(z)返回true,那么x.equals(z)也应该返回true。 4. 一致性:对于任何非空引用x和y,多次调用x.equals(y)应该始终返回相同的结果在使用HashSet的时候,为了保证对象的唯一性,需要重写对象的hashCodeequals方法。 hashCode方法用于生成对象的哈希码,HashSet在添加对象时会使用该哈希码来判断对象是否重复。 equals方法用于判断两个对象是否相等。如果重写了hashCode方法,一般也要重写equals方法。 重写这两个方法时,需要遵循以下规则: 1.如果两个对象相等,那么它们的hashCode值一定相等。 2.如果两个对象的hashCode值相等,那么它们不一定相等。 3.equals方法需要遵循传递性,对称性和自反性

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值