再探HashTable和HashMap

来源:互联网 发布:国外国内四大数据库 编辑:程序博客网 时间:2024/06/02 02:44

(首先声明我在最近的博客里很多都采用了再探这个词,但这并不是说我第二次看,看了很多次,哪次有新的体会,有心得了,才会动笔去记录,声明一下)

这是之前记录的(已经是总结几次之后的版本)

hashmap和 hashtable区别

1HashMap是非线程安全的,HashTable是线程安全的。

2HashMap的键和值都允许有null值存在,而HashTable则不行。

3、因为线程安全的问题,HashMap效率比HashTable的要高。

4 hash算法不同,HashMap能更广泛地分散到数组的不同位置

5 扩展数组的算法不同,HashMap:原数组长度* 2,HashTable2 *原数组长度+1


这次是看别人的博客,一个我看了N篇,至今重新回味都觉得写得很棒的一篇文章。

链接:http://www.cnblogs.com/ITtangtang/p/3948406.html

下面是我读的时候做的笔录还有新的体会。

1:hashMap类不保证不保证映射的顺序,特别是它不保证该顺序恒久不变

2:HashMap不是线性安全的,但是可以变成线性安全的

方法:

 Map map = Collections.synchronizedMap(new HashMap());//对HashMap真不错3:HashMap中的EntryHashMap其实就是一个Entry数组,Entry对象中包含了键和值,其中next也是一个Entry对象,它就是用来处理hash冲突的,形成一个链表。4:HashMap,HashTable计算索引的方法
HashMap:  hash & (length-1);  //这里不能随便算取,用hash&(length-1)是有原因的,这样可以确保算出来的索引是在数组大小范围内,不会超出HashMap中则通过h&(length-1)的方法来代替取模,同样实现了均匀的散列,但效率要高很多,这也是HashMap对Hashtable的一个改进。
HashTable: hash值对length取模(即除法散列法),这种方法基本能保证元素在哈希表中散列的比较均匀,但取模会用到除法运算,效率很低
5 为什么哈希表的容量一定要是2的整数次幂
首先,length为2的整数次幂的话,h&(length-1)就相当于对length取模,这样便保证了散列的均匀,同时也提升了效率;
其次,length为2的整数次幂的话,为偶数,这样length-1为奇数,奇数的最后一位是1,这样便保证了h&(length-1)的最后一位可能为0
也可能为1(这取决于h的值),即与后的结果可能为偶数,也可能为奇数,这样便可以保证散列的均匀性,而如果length为奇数的话
很明显length-1为偶数,它的最后一位是0,这样h&(length-1)的最后一位肯定为0,即只能为偶数,这样任何hash值都只会被散列到
数组的偶数下标位置上,这便浪费了近一半的空间,因此,length取2的整数次幂,是为了使不同hash值发生碰撞的概率较小,这样就
能使元素在哈希表中均匀地散列。
6添加新的元素的时候在Entry链中是添加到链的头部
7关于扩容
HashMap扩容是扩展为原来的二倍,至于为什么扩展到二倍上面有叙述。
当HashMap中的元素越来越多的时候,hash冲突的几率也就越来越高,因为数组的长度是固定的。所以为了提高查询的效率
就要对HashMap的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,这是一个常用的操作,而在HashMap数组扩容之后
最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize
新建了一个HashMap的底层数组,调用transfer方法,将HashMap的全部元素添加到新的HashMap中,并重新计算元素在新的数组中的索引位置
8负载因子
loadFactor:负载因子loadFactor定义为:散列表的实际元素数目(n)/ 散列表的容量(m)。

  HashMap的实现中,通过threshold字段来判断HashMap的最大容量:

threshold = (int)(capacity * loadFactor);  

  结合负载因子的定义公式可知,threshold就是在此loadFactor和capacity对应下允许的最大元素数目,超过这个数目就重新resize

以降低实际的负载因子。默认的的负载因子0.75是对空间和时间效率的一个平衡选择。当容量超出此最大容量时

resize后的HashMap容量是容量的两倍:



1 0