重写equals为什么要重写hashcode

​Java设计的顶级父类Object类中,有两个方法很特殊,它们分别是equals方法与hashCode方法。——一旦重写了equals方法,就一定要重写hashCode方法。以下是Object的源码:

public class Object {

  public boolean equals(Object obj) {
    return (this == obj);
  }


  public int hashCode() {
    return identityHashCode(this);
  }


  /* package-private */ static int identityHashCode(Object obj) {
    int lockWord = obj.shadow$_monitor_;
    final int lockWordStateMask = 0xC0000000;  // Top 2 bits.
    final int lockWordStateHash = 0x80000000;  // Top 2 bits are value 2 (kStateHash).
    final int lockWordHashMask = 0x0FFFFFFF;  // Low 28 bits.
    if ((lockWord & lockWordStateMask) == lockWordStateHash) {
      return lockWord & lockWordHashMask;
    }
    return identityHashCodeNative(obj);
  }


}

我们知道判断的时候先根据hashcode进行的判断,相同的情况下再根据equals()方法进行判断。如果只重写了equals方法,而不重写hashcode的方法,会造成hashcode的值不同,而equals()方法判断出来的结果为true。

   在Java中的一些容器中,不允许有两个完全相同的对象,插入的时候,如果判断相同则会进行覆盖。这时候如果只重写了equals()的方法,而不重写hashcode的方法,Object中hashcode是根据对象的存储地址转换而形成的一个哈希值。这时候就有可能因为没有重写hashcode方法,造成相同的对象散列到不同的位置而造成对象的不能覆盖的问题。

如何重写这两个方法?

例子:

    public class SimpleDemo {
	// 部门
	private String department;
	// 工号
	private int id;
 
	public SimpleDemo(int id, String department) {
		super();
		this.id = id;
		this.department = department;
	}
 
	public int getId() {
		return id;
	}
 
	public void setId(int id) {
		this.id = id;
	}
 
	public String getdepartment() {
		return department;
	}
 
	public void setdepartment(String department) {
		this.department = department;
	}
 
	@Override
	public int hashCode() {
		int hash = 1;
		hash = hash * 17 + id;
		hash = hash * 31 + department.hashCode();
		return hash;
	}
       @Override
	public boolean equals(Object obj) {
		if (obj == null)
			return false;
		if (obj == this)
			return true;
		if (obj instanceof SimpleDemo) {
			SimpleDemo sd = (SimpleDemo) obj;
			return sd.department.equals(department) && sd.id == id;
		}
		return false;
	}
public class Test02 {
    public static void main(String[] args) {
		SimpleDemo sdo1=new SimpleDemo(0106,"技术部");
		SimpleDemo sdo2=new SimpleDemo(0106,"技术部");        
        System.out.println(sdo1.equals(sdo2));
	}
}

​​​​​​​

首先我们写一个方法

public class Test {
    public static void main(String[] args) {
        String a = "ok";
        String b = new String("ok");

        System.out.println(a.hashCode());
        System.out.println(b.hashCode());
    }
}

输出结果:

a与b哈希冲突,它们的内存地址在计算机里是不一样的,那么地址不一样,为什么hashCode却一样呢?

 我们点开hashCode的源码

 首先给一个局部变量h,h默认为零(jdk定义),当h为0并且值的长度大于零,用char val [ ]代表一个字符数组,然后把这个数组做一个遍历,结果赋给hash并返回h。

所以,如果字符串的值是一模一样的,它们的hashCode值也相同。

equals方法和hashCode方法的关系:

如果两个对象相同(equals方法返回的是true),那么它们的hashCode值一定相同

如果两个对象不同(equals方法返回的是false),那么它们的hashCode值可能相同也可能不同

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值