1. 重写equals时hashCode方法也要重写
2. 集合中两个对象比较的顺序:先调用hashCode(),然后调用equals()
3. hashCode相等时,继续调用equals,表示两个对象可能相等可能不相等;
4. hashCode不相等时不调用equals,表示两个对象一定不相等;
另外,在HashMap中,HashCode的计算,是用来定位我们的键值对应该放到Hash表中哪个格子中的关键属性。而这个HashCode的计算方法是调用的各个对象自己的实现的hashCode()方法。而这个方法是在Object对象中定义的,所以我们自己定义的类如果要在集合中使用的话,就需要正确的覆写hashCode() 方法。下面就介绍一下应该如何正确覆写hashCode()方法。设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该生成同样的值。如果在将一个对象用put()方法添加进HashMap时产生一个hashCode()值,而用get()取出时却产生了另外一个hashCode()值,那么就无法重新取得该对象了。所以,如果你的hashCode()方法依赖于对象中易变的数据,那用户就要小心了,因为此数据发生变化时,hashCode()就会产生一个不同的hash码,相当于产生了一个不同的“键”。
此外,也不应该使hashCode()依赖于具有唯一性的对象信息,尤其是使用this的值,这只能产生很糟糕的hashCode()。因为这样做无法生成一个新的“键”,使之与put()种原始的“键值对”中的“键”相同。例如,如果我们不覆写Object的hashCode()方法,那么调用该方法的时候,就会调用Object的hashCode()方法的默认实现。Object的hashCode()方法,返回的是当前对象的内存地址。下次如果我们需要取一个一样的“键”对应的键值对的时候,我们就无法得到一样的hashCode值了。因为我们后来创建的“键”对象已经不是存入HashMap中的那个内存地址的对象了。- package intro.collections;
-
-
import java.util.*;
-
//身份证类
-
class Code{
-
final int id;//身份证号码已经确认,不能改变
-
Code(int i){
-
id=i;
-
}
-
//身份号号码相同,则身份证相同
-
public boolean equals(Object anObject) {
-
if (anObject instanceof Code){
-
Code other=(Code) anObject;
-
return this.id==other.id;
-
}
-
return false;
-
}
-
public String toString() {
-
return "身份证:"+id;
-
}
-
}
-
//人员信息类
-
class Person {
-
Code id;// 身份证
-
String name;// 姓名
-
public Person(String name, Code id) {
-
this.id=id;
-
this.name=name;
-
}
-
//如果身份证号相同,就表示两个人是同一个人
-
public boolean equals(Object anObject) {
-
if (anObject instanceof Person){
-
Person other=(Person) anObject;
-
return this.id.equals(other.id);
-
}
-
return false;
-
}
-
public String toString() {
-
return "姓名:"+name+" 身份证:"+id.id+"\n";
-
}
-
}
-
public class HashCodeTest {
-
public static void main(String[] args) {
-
HashMap map=new HashMap();
-
Person p1=new Person("张三",new Code(123));
-
map.put(p1.id,p1);//我们根据身份证来作为key值存放到Map中
-
Person p2=new Person("李四",new Code(456));
-
map.put(p2.id,p2);
-
Person p3=new Person("王二",new Code(789));
-
map.put(p3.id,p3);
-
System.out.println("HashMap 中存放的人员信息:\n"+map);
-
// 张三 改名为:张山 但是还是同一个人。
-
Person p4=new Person("张山",new Code(123));
-
map.put(p4.id,p4);
-
System.out.println("张三改名后 HashMap 中存放的人员信息:\n"+map);
-
//查找身份证为:123 的人员信息
-
System.out.println("查找身份证为:123 的人员信息:"+map.get(new Code(123)));
-
}
-
}
结果为:
HashMap 中存放的人员信息:
、{身份证:456=姓名:李四 身份证:456
, 身份证:123=姓名:张三 身份证:123
, 身份证:789=姓名:王二 身份证:789
}
张三改名后 HashMap 中存放的人员信息:
{身份证:456=姓名:李四 身份证:456
, 身份证:123=姓名:张三 身份证:123
, 身份证:123=姓名:张山 身份证:123
, 身份证:789=姓名:王二 身份证:789
}
查找身份证为:123 的人员信息:null
例子的输出结果表示,我们所做的更新和查找操作都失败了。失败的原因就是我们的身份证类:Code 没有覆写hashCode()方法。这个时候,当查找一样的身份证号码的键值对的时候,使用的是默认的对象的内存地址来进行定位。这样,后面的所有的身份证号对象new Code(123) 产生的hashCode()值都是不一样的。所以导致操作失败。
下面,我们给Code类加上hashCode()方法,然后再运行一下程序看看:
- class Code{
-
final int id;//身份证号码已经确认,不能改变
-
Code(int i){
-
id=i;
-
}
-
//身份号号码相同,则身份证相同
-
public boolean equals(Object anObject) {
-
if (anObject instanceof Code){
-
Code other=(Code) anObject;
-
return this.id==other.id;
-
}
-
return false;
-
}
-
public String toString() {
-
return "身份证:"+id;
-
}
-
//覆写hashCode方法,并使用身份证号作为hash值
-
public int hashCode(){
-
return id;
-
}
-
}
结果就为:
HashMap 中存放的人员信息:
{身份证:456=姓名:李四 身份证:456
, 身份证:789=姓名:王二 身份证:789
, 身份证:123=姓名:张三 身份证:123
}
张三改名后 HashMap 中存放的人员信息:
{身份证:456=姓名:李四 身份证:456
, 身份证:789=姓名:王二 身份证:789
, 身份证:123=姓名:张山 身份证:123
}
查找身份证为:123
的人员信息:姓名:张山 身份证:123
阅读(1313) | 评论(0) | 转发(0) |