equals方法重写,为什么hashcode方法也要重写

  • 重写子类的euquals方法,为什么一定要重写hashCode方法
public class HashCodeUse {
    public static void main(String[] args) {
        User user1 =new User("A", "女", 10, 100);
        User user2 =new User("A", "女", 10, 100);
        System.out.println(user1 == user2); // output:false
        System.out.println(user1); //output:com.study.day15.part2.User@17b6ded
        System.out.println(user2); //output:com.study.day15.part2.User@17b6ded
        System.out.println(user1.equals(user2)); // true
        HashMap hashMap = new HashMap();
        hashMap.put(user1, "user1的value");
        System.out.println(hashMap.get(user2)); // output:user1的值
    }
}
class User{
    String name;
    String gender;
    int age;
    int score;

    public User(String name, String gender, int age, int score) {
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.score = score;
    }
    
    // 重写User类的equals方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age && score == user.score && Objects.equals(name, user.name) && Objects.equals(gender, user.gender);
    }
    // hashCode方法同时被重写
    @Override
    public int hashCode() {
        return Objects.hash(name, gender, age, score);
    }
}
// 在HashMap的使用过程中会用到euqal方法,如果不改写hashcode值就会出现hash(user1)
// 不等于hash(user2),但是equals却相等的情况,会发生冲突;
  • 逐步理解hashMap的相关概念:

  • 基于hash算法的数据结构:hashMap(哈希映射),hashSet(hash集合),hashtable(hash表)

  • 首先理解哈希表(逻辑结构)

    哈希表以哈希函数h作为对应关系,目的是为了在查询目标记录时不需要进行遍历比较,而是一次直接获得想要的结果。因此将目标记录与其关键字之间建立一个哈希函数关系h,使每个关键字和结构中一个唯一的存储位置相对应。从而给定关键字key和对应关系h,通过h(key)找到目标记录value;

  • hash表是一种逻辑结构,而hashMaphashTable是Java中的数据结构,他们通过实现Hash表实现了相应的操作;

  • hashMap

    HashMap中的put(key,value)和get(key)方法,HashMap是使用hash算法,然后基于数组+链表+红黑树来实现的,HashMap内部数组的初始长度为16,并且还能自动扩容。探究一下put(key,value)和get(key)这两个常用的方法的实现过程和原理.

    • put(key,value)的原理

      调用put方法的时候,方法内部会调用hash(key)方法,计算出key的hash值h,然后通过HashMap的主干部分(数组tab)的长度length来进行位与运算(length-1)&h得出一个index=(length-1)&h值,然后直接根据index的值,将Node对象放入对应的tab[index]=Node即可

    • get(key)的原理

      一般情况下,首先根据key值调用方法hash(key),通过与数组长度位与运算来计算出index值,然后直接返回tab[index].value即可.
      但是当计算出的index处的Node对象是链表结构或红黑树时,这个时候会使用node.next来依次遍历比较链表上每个Node对象节点的key值是否和传入的key相等,直到匹配上为止。

  • hashMap的概念图

在这里插入图片描述

  • HashMap设计中选择了equals方法,所以对于不同的实例化对象,如果重写了父类equals方法,而不该写相应的hashcode()方法的话,可能相同属性的对象却拥有不同的hashcode()值,观察一下HashMap的get(key)操作,使用node.next来依次遍历比较链表上每个Node对象节点的key值是否和传入的key相等,也就是使用了key的equals()方法,在这种情况下,如果自己的类覆盖了equals()方法而没有管hashCode()方法,那么,在put(key)方法中,依赖hashCode计算出index这一步,就会将原本equals()的对象放在不同index中,这样接下来的覆盖操作就不会起作用了。造成的结果是,相等的对象被放入了不同index位置,而不是覆盖。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值