gpt4 book ai didi

Java用自定义的类作为HashMap的key值实例

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 27 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Java用自定义的类作为HashMap的key值实例由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

这是Java中很经典的问题,在面试中也经常被问起。其实很多书或者文章都提到过要重载hashCode()和equals()两个方法才能实现自定义键在HashMap中的查找,但是为什么要这样以及如果不这样做会产生什么后果,好像很少有文章讲到,所以写这么一篇来说明下.

首先,如果我们直接用以下的Person类作为键,存入HashMap中,会发生发生什么情况呢?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
keyword">public class Person {
 
   private String id;
 
   public Person(String id) {
     this .id = id;
   }
}
import java.util.HashMap;
 
public class Main {
   public static void main(String[] args) {
 
     HashMap<Person, String> map = new HashMap<Person, String>();
 
     map.put( new Person( "001" ), "findingsea" );
     map.put( new Person( "002" ), "linyin" );
     map.put( new Person( "003" ), "henrylin" );
     map.put( new Person( "003" ), "findingsealy" );
 
     System.out.println(map.toString());
 
     System.out.println(map.get( new Person( "001" )));
     System.out.println(map.get( new Person( "002" )));
     System.out.println(map.get( new Person( "003" )));
   }
}

那么输出结果是什么呢?

?
1
2
3
4
{Person @6e4d4d5e =henrylin, Person @275cea3 =findingsea, Person @15128ee5 =findingsealy, Person @4513098 =linyin}
null
null
null

我们可以看到,这里出现了两个问题:

1.在添加的过程中,我们将key=new Person("003")的键值对添加了两次,那么在期望中,HashMap中应该只存在一对这样的键值对,因为key(期望中)是相同的,所以不应该重复添加,第二次添加的value="findingsealy"应该替换掉原先的value="henrylin"。但是在输入中,我们发现期望中的情况并没有出现,而是在HashMap同时存在了value="findingsealy"和value="henrylin"的两个键值对,并且它们的key值还是不相同的,这显然是错误的.

2.在获取value值时,我们分别用三个Person对象去查找,这三个对象和我们刚刚存入的三个key值(在期望中)是相同的,但是查找出的却是三个null值,这显然也是错误的.

那么,正确的方法其实在很多地方都是被描述过了,直接对Person类进行修改,重载equals和hashCode方法,修改过后的Person类如下:

  。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Person {
 
   private String id;
 
   public Person(String id) {
     this .id = id;
   }
 
   @Override
   public boolean equals(Object o) {
     if ( this == o) return true ;
     if (o == null || getClass() != o.getClass()) return false ;
 
     Person person = (Person) o;
 
     if (id != null ? !id.equals(person.id) : person.id != null ) return false ;
 
     return true ;
   }
 
   @Override
   public int hashCode() {
     return id != null ? id.hashCode() : 0 ;
   }
}

那么,当我们重新执行上述的检验程序时,得到的结果如下:

  。

?
1
2
3
4
{Person @ba31 =findingsea, Person @ba32 =linyin, Person @ba33 =findingsealy}
findingsea
linyin
findingsealy

 可以看到,之前指出的亮点错误都得到了改正。那么,为什么会这样呢?

在HashMap中,查找key的比较顺序为:

1.计算对象的Hash Code,看在表中是否存在.

2.检查对应Hash Code位置中的对象和当前对象是否相等.

显然,第一步就是要用到hashCode()方法,而第二步就是要用到equals()方法。在没有进行重载时,在这两步会默认调用Object类的这两个方法,而在Object中,Hash Code的计算方法是根据对象的地址进行计算的,那两个Person("003")的对象地址是不同的,所以它们的Hash Code也不同,自然HashMap也不会把它们当成是同一个key了。同时,在Object默认的equals()中,也是根据对象的地址进行比较,自然一个Person("003")和另一个Person("003")是不相等的.

理解了这一点,就很容易搞清楚为什么需要同时重载hashCode()和equals两个方法了.

•重载hashCode()是为了对同一个key,能得到相同的Hash Code,这样HashMap就可以定位到我们指定的key上.

•重载equals()是为了向HashMap表明当前对象和key上所保存的对象是相等的,这样我们才真正地获得了这个key所对应的这个键值对.

还有一个细节,在Person类中对于hashCode()的重在方法为:

  。

?
1
2
3
4
@Override
public int hashCode() {
   return id != null ? id.hashCode() : 0 ;
}

 这里可能有疑惑的点在于:为什么可以用String类型的变量的Hash Code作为Person类的Hash Code值呢?这样new Person(new String("003"))和new Person(new String("003"))的Hash Code是相等的吗?

来看看以下代码的输出:

?
1
2
3
4
5
6
7
8
System.out.println( "findingsea" .hashCode());
System.out.println( "findingsea" .hashCode());
System.out.println( new String( "findingsea" ).hashCode());
System.out.println( new String( "findingsea" ).hashCode());
728795174
728795174
728795174
728795174

可以看到四条语句的输出都是相等的,很直观的合理的猜测就是String类型也重载了hashCode()以根据字符串的内容来返回Hash Code值,所以相同内容的字符串具有相同的Hash Code.

同时,这也说明了一个问题:为什么在已知hashCode()相等的情况下,还需要用equals()进行比较呢?就是因为避免出现上述例子中的出现的情况,因为根据对Person类的hashCode()方法的重载实现,Person类会直接用id这个String类型成员的Hash Code值作为自己的Hash Code值,但是很显然的,一个Person("003")和一个String("003")是不相等的,所以在hashCode()相等的情况下,还需要用equals()进行比较.

以下例子可以作为上述说明的佐证:

?
1
2
3
4
System.out.println( new Person( "003" ).hashCode()); // 47667
System.out.println( new String( "003" ).hashCode()); // 47667
 
System.out.println( new Person( "003" ).equals( new String( "003" ))); // false

以上这篇Java用自定义的类作为HashMap的key值实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我.

最后此篇关于Java用自定义的类作为HashMap的key值实例的文章就讲到这里了,如果你想了解更多关于Java用自定义的类作为HashMap的key值实例的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com