为什么重写equals必须重写hashCode

1. 为什么重写equals必须重写hashCode?

因为重写equals和hashcode才能保证对象的唯一性。

 * Note that it is generally necessary to override the {@code hashCode}
 * method whenever this method is overridden, so as to maintain the
 * general contract for the {@code hashCode} method, which states
 * that equal objects must have equal hash codes.

根据官方equals方法的注释:当equas方法被重写时,也要重写hashcode方法,以维护hashcode方法的一般约定。即相等的对象必须具有相等的哈希码。

2.为什么要保证对象的唯一性?使用场景有哪些?

我们在使用hashmap 等map形式的数据时,有时候要进行对象的判断,相同的属性意味着需求里的对象就是同一个对象。如:

public class User {
    String name;
    int code;
}

 HashSet<User> users = new HashSet<>();

 users.add(new User("lisi", 110));
 users.add(new User("lisi", 110));
 users.add(new User("ww", 111));
 
Iterator<User> iterator = users.iterator();
   while(iterator.hasNext()){
       User next = iterator.next();

       System.out.println(next);
   }

结果:

User{name='lisi', code=110}
User{name='lisi', code=110}
User{name='ww', code=111}

我们希望这两个lisi,只加入一个即可,因为在业务上,他们就是同一个人,没有必要加入两次。
加入集合的有两个相同的对象lisi,按照需求,相同的属性就是同一个对象,但是集合中依然两个属性一样的对象。这就违背了需求。
原因:
hashset无法判断他们是同一个对象导致。因为对象是否唯一,取决于equals 和hashcode的逻辑。因为没有重写,所以程序认为不是一个对象。

默认这种形式下,是否为同一个对象的判断使用的是object的equals和hashcode.查询源码

3.Object 源码 equals和hashcode

Object.class

//首先equals判断是对象之间的地址是否相同,大家知道,当执行new命令时,就会新建
//一个对象,产生一个新的内存地址。因此他们肯定不相同,所以程序认为不是一个对象。
public boolean equals(Object obj) {
       return (this == obj);
}
//本地方法  
/* Returns a hash code value for the object. This method is
 * supported for the benefit of hash tables such as those provided by
 * {@link java.util.HashMap}.
 * 返回一个hash值,有利于支持哈希表,如hashmap
 * /
//As far as is reasonably practicable, the {@code hashCode} method defined * by class {@code Object} returns distinct integers for distinct objects.
//合理可行的情况下,由类object的hashcode方法给不同的对象返回不同的整数。

public native int hashCode();

那这种形式是如何判断是否为同一个对象的呢?

4.判断对象是否相同

如果要解决上述问题,就要重写User对象的equals和hashcode方法
当重写了equals和hashcode方法时,当对象之间进行对比,
1.会先调用hashcode方法,它会根据对象的属性产生一个hash值,
2.在执行equals,先判断内存地址值是否相等,在判断是否为null,在判断属性是否相等。

还能够提高效率。当对象属性太多,equals就会臃肿,先判断hashcode,就可以避免无意义的执行。
如果hashcode不同,对象肯定不同。
如果hashcode相同,再去比较equas方法

    @Override
    public boolean equals(Object o) {
    //如果两个对象内存地址相同,肯定为同一个对象。返回true
        if (this == o) return true;
        //如果对象为null 等,false
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        //对比对象之间的属性是否相同,返回状态
        return code == user.code && name.equals(user.name);
    }

	/**
	* 根据对象的属性产生hash值。
	*/
    @Override
    public int hashCode() {
        return Objects.hash(name, code);
    }

4.1.调用顺序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值