java中重写equals()方法的时候为什么要重写hashCode()方法?

有时候,或许会听到被人说,在重写equals方法的时候,记得重写hashcode方法。那么自然有这样的疑问,那么为什么这样?equals方法和hashCode方法是什么关系?不重写的时候会有什么危害?文章将从一下几个方面进行叙述。


一:什么是hashCode(),equals()方法?

二:hashCode(),equals()两种方法是什么关系?

三:为什么在重写equals方法的时候要重写hashcode的方法?

四:怎么重写这两种方法?



一:什么是hashCode(),equals()方法?


关于equals()方法,经常说的就是比较的是内容(与==比较的地址相对),这么说不完全对--看下面这段代码:

学生类:

 public class Student {
	private int id;
	private String name;
        public Student(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
}

主测试类:

   public class Test {
      public static void main(String[] args) {
        Student s1=new Student(001,"邵小二");
        Student s2=new Student(001,"邵小二");
        System.out.println(s1.equals(s2));
    }
}

我们想通过一个学生的学号以及姓名来判断是否是同一个学生。可是 根据程序的运行结果(打印出的为false)来看,即使是学号与姓名两个字段都完全的相同,判断出的学生也不是相同的。

equals()在java.lang.Object下,其源码为:

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

即在Object中equals方法只是判断的为是否为同一个对象的引用。

在String类中,我们可以这样写,打印的结果为true。

         String str1="123";
         String str2="123";
         //print true
         System.out.println(str1.equals(str2));

这里是因为在String类中对equals方法进行了重写的原因。


什么是hashcode方法?在java中,对对象的存储采取了存储在哈希表中处理方法,hashcode方法是根据对象的地址转换之后返回的一个哈希值,其详细的用法在这篇文章涉及的时候详细的介绍过-点击打开链接



二:hashCode(),equals()两种方法是什么关系?


要弄清楚这两种方法的关系,就需要对哈希表有一个基本的认识。其基本的结构如下:


对于hashcode方法,会返回一个哈希值,哈希值对数组的长度取余后会确定一个存储的下标位置,如图中用数组括起来的第一列。

不同的哈希值取余之后的结果可能是相同的摸着时候就用equals方法判断是否为相同的对象,不同则在链表中插入。

则有:

hashcode不相同,用equals()方法判断的返回的一定为false。

hashcode相同,equals()方法返回值不能确认,可能为true,可能为false。




三:为什么在重写equals方法的时候要重写hashcode的方法?


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

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



四:怎么重写这两种方法?


关于重写equals()方法应该满足的原则,这里就不在赘述。只是通过一个小例子来对其有一个重写两个方法有一个新的认识。

        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,"技术部");
                //print true
               System.out.println(sdo1.equals(sdo2));
	}
}
























  • 56
    点赞
  • 189
    收藏
    觉得还不错? 一键收藏
  • 28
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值