学习hashMap总结

基于java 1.6

         HashMap和其他的Map一样,都有由key和它的value构成。但是不同的Map其key的存储方式是大不相同的。HashMap较其他Map具有更好的查询效率,这是由于HashMap采用了Hash算法。每一个key本身都具有一个获取hashCode的方法。这些hashCode通过hash算法,被转化为一个个序号,对应“横向”链表上的存储位置。

         当序号相同且key的值不同时,在这个位置上就会形成一个“纵向”的链表。在这个链表中先添加的key处于链表的末端,后添加的处于链表的前端。链表的存储单元为 Entry<k,y> ,在这个类中有一个还有一个类型为Entry<k,y>的参数,名为nextnext指向的是下一个Entry<k,y>的地址,HashMap就是以这样的方式形成了一个“纵向”的链表。

学习hashMap总结


       hashMap还具有自动扩张的功能。每当map中的容量达到threshold的时候,hashMap就会通过resize()方法扩张一倍。Resize()的过程是比较消耗性能的,所以如果事先知道存储的大概范围时,也可以预先设置Map的大小,从而降低扩张带来的消耗。threshold的算法是size*loadFactor,loadFactor是一个比例参数,决定了多大比例的长度作为threshold,一般而言loadFactor的值为0.75。如果一个hashMap的长度为16loadFactor的值为0.75,那么它的临界值为12,当添加的元素达到12时,这个map就会扩张一倍达到32.

 


hashMap可以通过构造函数在初始化的时候设置hashMap的各项参数。它提供的构造参数有HashMap(int size,float threshold)HashMap(int size),HashMap() HashMap(Map map)。size是指Map的大小,然而这个值不一定会成为HashMap的最终大小,它会最终转换为最接近 2的N次方值。在HashMap(int size,float threshold)的源码里,有这样的代码:

       其中j为最终的大小,i就是我们传递过来的size,通过位运算,j的最终取值为稍大于size的2的N次方值。以下是默认的构造函数HashMap():

学习hashMap总结

       可以看到loadFactor的默认值为0.75,默认临界值为12(并不是很大),而“横向”的链表其实只是一个数组。如果事先知道HashMap的大小,就应该使用HashMap(int size,float loadFactor)或HashMap(int size)为这个HashMap设置一个合适的大小。即便HashMap有着自动扩张的能力,但是这个功能会消耗不少性能,所以事先设置长度是更好的办法。

 


       hashMap的大小总是2n次方。这是经过计算得出的最佳大小,在这个大小上,hashCode的映射可以达到最小碰撞的效果。

      1.将key的hashCode经过HashMap的hash算法后获取的值设为A

      2.将HashMap的总长度设为S

那么这个key对应的hashMap中的位置实际应为table[A & (S-1)] 。如果总长度总为16,那么在16-1在二进制对应的值为1111,这个值具有最好的匹配度,因为它每一位都为1。它就像一面光滑的镜子,可以将Hash后的值均匀的映射到table的各个位置上。

参考文档:

http://alex09.iteye.com/blog/539545

http://www.iteye.com/topic/539465/

你可能感兴趣的:(HashMap)