`
ami1984
  • 浏览: 24954 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

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

阅读更多

      重写hashCode()时最重要的原因就是:无论何时,对同一个对象调用hashCode()都应该生成同样的值。如果在将一个对象用put()方法添加进HashMap时产生一个hashCode()值,而用get()取出时却产生了另外一个 hashCode()值,那么就无法重新取得该对象了。所以,如果你的hashCode()方法依赖于对象中易变的数据,那用户就要小心了,因为此数据发生变化时,hashCode()就会产生一个不同的hash码,相当于产生了一个不同的“键”。 

      Object的hashCode()方法,返回的是当前对象的内存地址。下次如果我们需要取一个一样的“键”对应的键值对的时候,我们就无法得到一样的hashCode值了。因为我们后来创建的“键”对象已经不是存入HashMap中的那个内存地址的对象了。

      我们看一个简单的例子,就能更加清楚的理解上面的意思。假定我们写了一个类: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 的人员信息:【姓名】:张山 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics