A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© chen20134 中级黑马   /  2014-3-17 14:08  /  895 人查看  /  1 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

在java中,存取数据的性能,一般来说当然是首推数组,但是在数据量稍大的容器选择中,Hashtable将有比数组性能更高的查询速度.具体原因看下面的内容。

Hashtable在存储数据时,一般先将作为key的对象的HashCode和0x7FFFFFFF做与操作,因为一个对象的HashCode可以为负数,这样操作后可以保证它为一个正整数.然后以Hashtable的长度取模,得到值对象在Hashtable中的索引。
index = (o.hashCode() & 0x7FFFFFFF)%hs.length;这个值对象就会直接放在Hashtable的第index位置。对于写入,这和数组一样,把一个对象放在其中的第index位置,但如果是查询,经过同样的算法,Hashtable可以直接通过key得到index,从第index取得这个值对象,而数组却要做循环比较;所以对于数据量稍大时,Hashtable的查询比数据具有更高的性能。
虽然不同对象有不同的hashCode,但不同的hashCode经过与长度的取余,就很可能产生相同的index。极端情况下会有大量的对象产生一个相同的索引,这就是关系Hashtable性能问题的最重要的问题:Hash冲突。
一个设计各好的HashTable,一般来说会比较平均地分布每个元素,因为Hashtable的长度总是比实际元素的个数按一定比例进行自增(装填因子一般为0.75左右),这样大多数的索引位置只有一个对象,而很少的位置会有几个元素。
Hashtable中的每个位置存放的是一个链表,对于只有一个对象的位置,链表只有一个首节点(Entry),Entry的next为null.然后有hashCode,key,value属性保存了该位置的对象的HashCode,key和value(对象本身);如果有相同索引的对象进来则会进入链表的下一个节点。如果同一个索引中有多个对象,根据HashCode和key可以在该链表中找到一个和查询的key相匹配的对象。
对于HashMap和Hashtable的存取性能有重大影响的首先是应该使该数据结构中的元素尽量大可能具有不同的HashCode,虽然这并不能保证不同的HashCode产生不同的index,但相同的HashCode一定产生相同的index,从而影响产生Hash冲突。
对于一个象,如果具有很多属性,如果所有属性都参与散列,当然hashCode的多样性将大大提高,但牺牲了性能。如equals比较,如果太多的对象参与了散列,那么需要的操作常数时间将会增加很大;而如果只能少量的属性采样散列,极端情况会产生大量的散列冲突。
从实现来说,一般的HashCode方法会这样:
return Attribute1.HashCode() + Attribute1.HashCode()..[+super.HashCode()]。
我们知道,每次调用这个方法,都要重新对方法内的参与散列的对象重新计算一次它们的HashCode的运算,如果一个对象的属性没有改变,仍然要每次都进行计算,所以如果设置一个标记来缓存当前的散列码,只要当参与散列的对象改变时才重新计算,否则调用缓存的hashCode,这可以从很大程度上提高性能。
默认的实现是将对象内部地址转化为整数作为HashCode,因为不同的对象内部地址肯定不同,这当然能保证每个对象具有不同的HasCode。但java语言并不能让程序员获取对象内部地址,所以,让每个对象产生不同的HashCode有着很多可研究的技术。
如何对HashCode的性能和多样性求得一个平衡,可以参考相关算法设计的书,其实并不一定要求非常的优秀,只要能尽最大可能减少散列值的聚集。重要的是我们应该记得HashCode对于我们的程序性能有着重要的影响,在程序设计时应该时时加以注意。

评分

参与人数 1技术分 +1 收起 理由
何伟超 + 1

查看全部评分

1 个回复

倒序浏览
楼主研究很深入,我也正在看这个,只是看的比较慢
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马