前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jdk源码分析之HashMap--为什么key不建议是可变对象

jdk源码分析之HashMap--为什么key不建议是可变对象

作者头像
叔牙
发布2020-11-19 14:52:36
4860
发布2020-11-19 14:52:36
举报
文章被收录于专栏:一个执拗的后端搬砖工

接着之前的文章,我们死磕HashMap的每一个细节和用法。我们都知道创建HashMap的时候如果不指定类型,默认是HashMap<Object,Object>类型(其实就算指定了编译后也是Object类型,此处不做赘述),可能我们大部分人停留在使用层面,并没有对底层的源码实现有过过多的分析和研究,那么我们首先抛出今天的议题,为什么不建议HashMap的key使用可变对象呢?更进一步说,为什么有些公司或团队强制使用HashMap的key使用String,Long等等不可变对象呢?

在详细介绍答案之前,再问一个问题,在代码使用层面,如果key是可变对象,对我们的get查询操作有影响吗?有什么影响?

首先,还是先看一下get方法的代码:

第一个红线处直接使用null作为到数组0号位置的链表中查询,null是不可变的可以忽略,直接看第二个红线处,根据非null得key查询,看一下实现:

我们今天分析的核心就是hash方法,其功能就是根据key计算出hash值,然后用来映射到Entry<K,V>中的位置,接着看hash方法实现:

该方法的意思是,如果hashSeed不等于0且key是String的实例,直接调用底层的Hashing.stringHash32方法返回hash值,否则基于key的hashCode做散列运算,尽可能的减少碰撞,然后返回比较分散的hash值。

简单从源码层面做了一下分析,那么key是否可变与hash计算有关系吗?没错,还真有关系,hash方法是基于key的hashCode做的散列运算,那么当然不同的key有不同的hashcode(非绝对),hash方法同样会算出不同的hash值,然后映射到数组不同的位置,这一点是没有疑问的。

那假如说key是可变对象,比如说key是一个人,value是他的工作信息,第一次put之后,插入到Entry<K,V> 数组具体位置,那如果这个key对应的人对象内部属性发生变化,体重变动,那么会导致key的hashcode发生变化,反映到get操作就是,hash散列运算和之前得到的hash值发生变化,直接导致indexFor()方法映射到的 Entry<K,V>数组位置发生变化,结果就是根据这个key永远无法再找到之前插入的数据了,如果很多key都发生变化,会导致:

  1. HashMap中存在很多无法被找到的key-value
  2. 由于存在很多无用的数据,有用的key-value查询和遍历变得效率低下

所以使用HashMap或者其他Map实例的时候,根据业务场景尽可能避免使用可变对象作为key,最常用的就是 Map<String,Object>或者Map<String,T>。

本篇篇幅较短,但是同样希望给大家在开发过程中带来更好的效率和体验。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-12-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PersistentCoder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档