也谈HashMap

刚看了一下http://www.iteye.com/topic/539465, 是annegu童鞋写的关于java中HashMap的实现原理。

我可以总结一下要点

1.HashMap的数据结构是 数组 和 数组中的链表

2.hash算法先根据hash值进行 hashcode%数组长度的运算 得到存储的位置,然后根据元素key在相应的位置中的链表中取到相应的值(前一步用到我们经常说的hashcode,后一步用到我们经常说的equal方法)

3.为了提高性能,java实现中 用 hashcode & (数组长度 - 1) 替换 hashcode%数组长度 的运算

4.HashMap 初始化大小时,总是设定为2的n次方 ,效果最佳。否则,按照 hashcode%数组长度的运算 就会浪费数组空间

5.如果可以预知map的大小,初始化一个 0.75*size > 估计map大小 中的 size值,用来降低HashMap resize时的能耗。其中0.75是loadfactor的默认值。loadfactor是当 元素个数/map大小 = loadfactor HashMap需要扩充。

 

其实有些人看完原文,还是会觉得云里雾里的感觉。这是因为对java的某些技术概念并不清楚。我这里自然用不着过多解释。随便网上一搜,便出来一大堆。其中http://topic.csdn.net/u/20070101/20/6315cbf9-43fd-485e-9bb8-47efa4cd0668.html中有一个人解释hashcode,equal解释的非常好,我不妨就贴在这里。该人用桶来比喻位置实在是很恰当。

 

1.hashcode是用来查找的,如果你学过数据结构就应该知道,在查找和排序这一章有
例如内存中有这样的位置
0     1     2     3     4     5     6     7    
而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,如果不用hashcode而任意存放,那么当查找时就需要到这八个位置里挨个去找,或者用二分法一类的算法。
但如果用hashcode那就会使效率提高很多。
我们这个类中有个字段叫ID,那么我们就定义我们的hashcode为ID%8,然后把我们的类存放在取得得余数那个位置。比如我们的ID为9,9除8的 余数为1,那么我们就把该类存在1这个位置,如果ID是13,求得的余数是5,那么我们就把该类放在5这个位置。这样,以后在查找该类时就可以通过ID除 8求余数直接找到存放的位置了。

2.但是如果两个类有相同的hashcode怎么办那(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?在这个时候就需要定义   equals了。
也就是说,我们先通过   hashcode来判断两个类是否存放某个桶里,但这个桶里可能有很多类,那么我们就需要再通过   equals   来在这个桶里找到我们要的类。
那么。重写了equals(),为什么还要重写hashCode()呢?
想想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不通过重写hashcode()来找到桶,光重写equals()有什么用啊
3。你要对A类排序,有两种方法,一种就是让A类实现comparabole结构并实现compareTo()方法,那么可以通过Collections.sort(List <A>   list)对其进行排序
另一种方法:自己定义一个类B实现Comparator类并实现compare方法,
然后通过Collections.sort(List <A>   list,B   b)进行排序

/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值