`

【转】JAVA中重写equals()方法为什么要重写hashcode()方法说明【一】

    博客分类:
  • Java
 
阅读更多

重写hashCode()时最重要的原因就是:无论何时,对同一个对象调用hashCode()都应该生成同样的值。如果在将一个对象用put()方法添加进HashMap时产生一个hashCode()值,而用get()取出时却产生了另外一个 hashCode()值,那么就无法重新取得该对象了。所以,如果你的hashCode()方法依赖于对象中易变的数据,那用户就要小心了,因为此数据发生变化时,hashCode()就会产生一个不同的hash码,相当于产生了一个不同的“键”。 
      Object的hashCode()方法,返回的是当前对象的内存地址。下次如果我们需要取一个一样的“键”对应的键值对的时候,我们就无法得到一样的hashCode值了。因为我们后来创建的“键”对象已经不是存入HashMap中的那个内存地址的对象了。 

1、 为什么要重载equal方法?

 

答案:因为Object的equal方法默认是两个对象的引用的比较,意思就是指向同一内存,地址则相等,否则不相等;如果你现在需要利用对象里面的值来判断是否相等,则重载equal方法。

 

2、 为什么重载hashCode方法?

 

答案:一般的地方不需要重载hashCode,只有当类需要放在HashTable、HashMap、HashSet等等hash结构的集合时才会 重载hashCode,那么为什么要重载hashCode呢?就HashMap来说,好比HashMap就是一个大内存块,里面有很多小内存块,小内存块 里面是一系列的对象,可以利用hashCode来查找小内存块hashCode%size(小内存块数量),所以当equal相等时,hashCode必 须相等,而且如果是object对象,必须重载hashCode和equal方法。

 

3、 为什么equals()相等,hashCode就一定要相等,而hashCode相等,却不要求equals相等?

 

答案:1、因为是按照hashCode来访问小内存块,所以hashCode必须相等。

 

          2、HashMap获取一个对象是比较key的hashCode相等和equal为true。

 

之所以hashCode相等,却可以equal不等,就比如ObjectA和ObjectB他们都有属性name,那么hashCode都以name计算,所以hashCode一样,但是两个对象属于不同类型,所以equal为false。

 

4、 为什么需要hashCode?

 

答案:1、 通过hashCode可以很快的查到小内存块。
         2、 通过hashCode比较比equal方法快,当get时先比较hashCode,如果hashCode不同,直接返回false。

===========================华丽的分割线============================

转载:http://ami1984.iteye.com/blog/683762

我们看一个简单的例子,就能更加清楚的理解上面的意思。假定我们写了一个类:Person (人),我们判断一个对象“人”是否指向同一个人,只要知道这个人的身份证号一直就可以了。 
      先来个没有重写Code类的hashcode()的例子吧,看看是什么效果:

package com.fit;

import java.util.HashMap;

/**
 * 身份证类
 * 
 * @author ZYD
 * 
 */
public class Code {

	/**
	 * 身份证号码,一旦确定就不能更改
	 */
	private final int id;

	public int getId() {
		return id;
	}

	/**
	 * 通过构造方法确定身份证号码
	 * 
	 * @param id
	 */
	public Code(int id) {
		this.id = id;
	}

	/**
	 * 重写equals()方法
	 */
	public boolean equals(Object o) {
		// 如果地址一样,则两个对象相同
		if (this == o) {
			return true;
		}
		// 如果两个对象是同一类型,则比较其属性值是否都相同。如果都相同,则说明两个对象也相同;否则,说明这两个对象不相同。
		if (o instanceof Code) {
			Code co = (Code) o;
			boolean b = (co.id == this.id);
			return b;
		}
		return false;
	}

	/**
	 * 重写toString()方法
	 */
	public String toString() {
		return "【身份证】:" + id;
	}
	
	/**
	 * 测试
	 * @param args
	 */
	public static void main(String[] args) {
		
		 HashMap<Code, Person> map = new HashMap<Code, Person>();
		 
		 Person p1 = new Person(new Code(10001),"张三");
		 Person p2 = new Person(new Code(10002),"李四");
		 
		 map.put(p1.getCode(), p1);
		 map.put(p2.getCode(), p2);
		 
		 System.out.println("HashMap 中存放的人员信息:\n"+map);
		 
		 //张三改名为张山,身份证号不变。
		 Person p3 = new Person(new Code(10001),"张山");
		 map.put(p3.getCode(), p3);
		 
		 System.out.println("张三改名为张山后 HashMap 中存放的人员信息:\n"+map);
		 
		 //查找身份证为10001 的人员信息
		 System.out.println("查找身份证为:10001 的人员信息:"+map.get(new Code(10001)));
	}
}

/**
 * 人类
 * @author Administrator
 *
 */
class Person {

	/**
	 * 每一个成人都有一个身份证
	 */
	private Code code;

	/**
	 * 姓名
	 */
	private String name;

	public Code getCode() {
		return code;
	}

	public void setCode(Code code) {
		this.code = code;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Person() {

	}

	public Person(Code code, String name) {
		this.code = code;
		this.name = name;
	}

	/**
	 * 重写equals()方法 当两个人得身份证号相同以及姓名相同时,表示这两个人是同一个人。
	 */
	public boolean equals(Object o) {
		if (o == this) {
			return true;
		}
		if (o instanceof Person) {
			Person p = (Person) o;
			boolean b = this.code.equals(p.code) && this.name.equals(p.name);
			return b;
		}
		return false;
	}

	/**
	 * 重写toString()方法
	 */
	public String toString() {
		return "【姓名】:" + name + "  ";
	}
}

 运行结果:

 

HashMap 中存放的人员信息:
{【身份证】:10002=【姓名】:李四  , 【身份证】:10001=【姓名】:张三  }
张三改名为张山后 HashMap 中存放的人员信息:
{【身份证】:10002=【姓名】:李四  , 【身份证】:10001=【姓名】:张三  , 【身份证】:10001=【姓名】:张山  }
查找身份证为:10001 的人员信息:null

 

从上面的结果可以看出:

 

我们所做的更新和查找操作都失败了。失败的原因就是我们的身份证类:Code 没有覆写hashCode()方法。这个时候,当查找一样的身份证号码的键值对的时候,使用的是默认的对象的内存地址来进行定位。这样,后面的所有的身份证号对象

new Code(10001) 产生的hashCode()值都是不一样的,所以导致操作失败。

 

 

 重写Code类的hashcode(),代码上:

package com.fit;

import java.util.HashMap;

/**
 * 身份证类
 * 
 * @author ZYD
 * 
 */
public class Code {

	/**
	 * 身份证号码,一旦确定就不能更改
	 */
	private final int id;

	public int getId() {
		return id;
	}

	/**
	 * 通过构造方法确定身份证号码
	 * 
	 * @param id
	 */
	public Code(int id) {
		this.id = id;
	}

	/**
	 * 重写equals()方法
	 */
	public boolean equals(Object o) {
		// 如果地址一样,则两个对象相同
		if (this == o) {
			return true;
		}
		// 如果两个对象是同一类型,则比较其属性值是否都相同。如果都相同,则说明两个对象也相同;否则,说明这两个对象不相同。
		if (o instanceof Code) {
			Code co = (Code) o;
			boolean b = (co.id == this.id);
			return b;
		}
		return false;
	}

	/**
	 * 重写hashcode()方法,以身份证号码作为hash码。
	 * 
	 * @return
	 */
	public int hashCode() {
		return id;
	}

	/**
	 * 重写toString()方法
	 */
	public String toString() {
		return "【身份证】:" + id;
	}
	
	/**
	 * 测试
	 * @param args
	 */
	public static void main(String[] args) {
		
		 HashMap<Code, Person> map = new HashMap<Code, Person>();
		 
		 Person p1 = new Person(new Code(10001),"张三");
		 Person p2 = new Person(new Code(10002),"李四");
		 
		 map.put(p1.getCode(), p1);
		 map.put(p2.getCode(), p2);
		 
		 System.out.println("HashMap 中存放的人员信息:\n"+map);
		 
		 //张三改名为张山,身份证号不变。
		 Person p3 = new Person(new Code(10001),"张山");
		 map.put(p3.getCode(), p3);
		 
		 System.out.println("张三改名为张山后 HashMap 中存放的人员信息:\n"+map);
		 
		 //查找身份证为10001 的人员信息
		 System.out.println("查找身份证为:10001 的人员信息:"+map.get(new Code(10001)));
	}
}

/**
 * 人类
 * @author Administrator
 *
 */
class Person {

	/**
	 * 每一个成人都有一个身份证
	 */
	private Code code;

	/**
	 * 姓名
	 */
	private String name;

	public Code getCode() {
		return code;
	}

	public void setCode(Code code) {
		this.code = code;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Person() {

	}

	public Person(Code code, String name) {
		this.code = code;
		this.name = name;
	}

	/**
	 * 重写equals()方法 当两个人得身份证号相同以及姓名相同时,表示这两个人是同一个人。
	 */
	public boolean equals(Object o) {
		if (o == this) {
			return true;
		}
		if (o instanceof Person) {
			Person p = (Person) o;
			boolean b = this.code.equals(p.code) && this.name.equals(p.name);
			return b;
		}
		return false;
	}

	/**
	 * 重写toString()方法
	 */
	public String toString() {
		return "【姓名】:" + name + "  ";
	}
}

 

运行效果:

HashMap 中存放的人员信息:
{【身份证】:10001=【姓名】:张三  , 【身份证】:10002=【姓名】:李四  }
张三改名为张山后 HashMap 中存放的人员信息:
{【身份证】:10001=【姓名】:张山  , 【身份证】:10002=【姓名】:李四  }
查找身份证为:10001 的人员信息:【姓名】:张山 

 

分享到:
评论

相关推荐

    Java重写equals同时需要重写hashCode的代码说明

    Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.

    重写equals和hashcode方法_equals_重写equals和hashcode方法_

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是Object类中的两个核心方法,所有类都默认继承自Object类。这两个方法在处理对象比较和集合操作时起着至关重要的作用。当我们创建自定义类并需要对对象进行精确...

    Java_重写equals()和hashCode()

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是对象的基本组成部分,它们在很多场景下都发挥着至关重要的作用。这两个方法与对象的相等性比较和哈希表(如HashMap、HashSet)的运作紧密相关。这篇博客将深入...

    重写equals方法

    第二种情况:对于采用哈希算法的集合,集合中对象必须重写 hashCode 方法,同时也要重写 equals 方法。这是因为哈希算法需要使用 hashCode 方法来计算对象的哈希值,而 equals 方法用于判断两个对象是否相等。 如何...

    为什么重写equals方法,还必须要重写hashcode方法

    为什么重写equals方法,还必须要重写hashcode方法

    java中重写equals()方法的同时要重写hashcode()方法(详解)

    Java 中重写 equals() 方法的同时要重写 hashCode() 方法的重要性 在 Java 中,equals() 方法和 hashCode() 方法是两个紧密相关的方法,它们都是用于比较和标识对象的方法。equals() 方法用于比较两个对象的值是否...

    关于重写equals,hashcode以及compareTo方法!

    关于重写equals、hashcode以及compareTo方法! equals()方法是Object类中的一个方法,它用于比较两个对象是否相等。然而,它的默认实现是比较对象的引用(地址),而不是比较对象的实际内容。因此,在某些情况下,...

    Java重写equals及hashcode方法流程解析

    "Java重写equals及hashcode方法流程解析" Java中的equals和hashCode方法是两个非常重要的方法,它们都是Object类中的方法。在实际开发中,正确地重写这两个方法对于确保程序的正确性和性能至关重要。下面,我们将...

    为什么在重写 equals方法的同时必须重写 hashcode方法

    在 Java 中,`equals` 和 `hashCode` 方法是 Object 类中的两个重要方法,它们用于比较对象的相等性。默认情况下,`equals` 方法比较的是两个对象的引用,即是否指向内存中的同一个位置,而 `hashCode` 方法则返回...

    equals方法的重写.docx

    #### 二、为什么需要重写equals方法? 1. **提高程序效率**:当两个对象具有相同的业务逻辑上的“身份”时,它们应该被认为是相等的。 2. **增强代码可读性**:重写后的`equals`方法可以根据实际需求来判断对象是否...

    java中为何重写equals时必须重写hashCode方法详解

    现在,让我们深入探讨为什么重写 `equals()` 时要重写 `hashCode()`: 1. **一致性**:一旦对象被创建并赋予了特定的值,其 `equals()` 和 `hashCode()` 方法的结果就应该保持不变,即使在程序的不同执行期间也是...

    equals与hashCode在实际开发中的重写写法

    在 TestEqualsHashCode.java 文件中,通常会包含一个示例,演示如何正确地重写 `equals()` 和 `hashCode()` 方法。这个文件可能包含一个自定义类,并展示如何根据类的属性定义这两个方法,以实现特定的比较逻辑。 ...

    Java中的equals和hashCode方法详解1

    在Java编程语言中,`equals()`和`hashCode()`方法是对象的基本组成部分,它们主要用于对象的比较和存储。这两个方法在`java.lang.Object`类中定义,因此所有的Java类都默认继承了这两个方法。然而,根据具体的应用...

    Java中equals,hashcode和==的区别

    Java 中 equals、hashcode 和==的区别是 Java 编程语言中一个经常遇到的问题。这三个概念都是用来比较对象的,但是它们之间存在着本质的区别。 首先,==号是Java中的一个运算符,用于比较两个对象的内存地址是否...

    java中hashcode和equals的详解.pdf

    equals 方法是 Java 中一个非常重要的方法,因为它是 Object 类中的一个基本方法,每个对象都可以根据自己的需求来重写这个方法。 三、hashCode 和 equals 方法的关系 hashCode 和 equals 方法之间存在着紧密的...

    【面试】hashCode与equals两者之间的关系 / == 和equals / 为什么要重写equals方法 / 重写equals /hashcode方法 / 为什么要重写hashCode方法

    3、**为什么要重写equals()方法?** 默认情况下,`equals()`方法继承自`Object`类,比较的是对象的引用。在处理自定义类时,我们可能关心的是对象的属性是否相等,而不是它们的内存地址。因此,为了基于对象的内容...

    关于hashCode()和equals()的本质区别和联系

    为什么需要重写 hashCode() 和 equals() 方法 在 Java 中,有很多类忽略了 hashCode() 和 equals() 方法的默认实现,以便提供更深层次的语义可比性。例如,Integer 类重写了 equals() 方法,使得两个 Integer 对象...

    why在重写equals时还必须重写hashcode方法分享

    现在,解释为什么在重写 `equals()` 时通常也要重写 `hashCode()`: 1. **一致性**:根据 Java 的 `Object` 类文档,如果两个对象通过 `equals()` 方法比较为相等,那么它们的 `hashCode()` 方法应该返回相同的值。...

    java中重写equals和重写hashCode()

    为什么在重写 `equals()` 后需要重写 `hashCode()` 呢?假设我们有一个自定义类,并且只重写了 `equals()` 方法。现在,有两个内容相等但内存地址不同的对象,当我们将它们放入 `HashMap` 时,`equals()` 方法可能会...

Global site tag (gtag.js) - Google Analytics