先上HashTable的继承关系:
HashTable继承关系图
为了方便比较同时放出HashMap的继承关系:
HashMap的继承关系可以看出HahMap和HashTable都实现了Map接口,只是父类不一样
HashTable的计算哈希是直接取得key本身的哈希:
int hash = key.hashCode();
这里可以看出,hashtable是不支持null值的,并且在put的时候取哈希之前已经判定了value为空判定,虽然key没有判定,但是在取hash的时候由于key是null所以一定会抛出java.lang.NullPointerException
if (value == null) {
throw new NullPointerException();
}
HashTable每次扩容是原有容量的2倍+1( (oldCapacity << 1) + 1),通过rehash()来实现扩容的
HashTable是的每个哈希桶的元素都是链表,相对来说如果每个哈希桶元素比较多的话,处理效率是比较低的,接下来划重点,这实质就是哈希表的实质,一张课表
课表
我们首先取得今天的日期,比如星期三,然后一节一节比较,寻找文体活动这门课,毕竟大家都不喜欢上课,过程和HashTable完全一致
哈希桶就相当于一个表格,首先从X轴取得哈希桶位置再在Y轴比较获取元素真实位置。
HashTable的计算索引的方式是:
(hash & 0x7FFFFFFF) % tab.length
这里为什么要与0x7FFFFFFF是因为Hash的值会是负数,0x7FFFFFFF是Integer.MAX_VALUE,使用Math.abs()也可以达到想用的效果,但是为什么不用它呢
主要原因如下图所示:
0x7FFFFFFF 和Math.abs()的区别
计算结果
可以看到当hash为Integer的最小值的时候,会导致Math.abs取得负数值,这样计算出来的index下标也是负值,而java的数组下标不能为负数,否则会导致程序异常
最终将node追加到哈希哈希桶某个哈西位置的尾部,就完成了整个存储过程
需要注意的是:HashTable是线程安全的,HashTable所有public方法都添加了synchronized关键字,保证线程同步不会出错。但是同时因为线程安全机制导致HashTable的存取效率不如HashMap
比较上一篇文章 JDK HashMap详解 而言,HashTable虽然都实现了Map接口,但各自有着不同的应用场景,总结起来有如下不同点:
- HashTable是线程安全的,HashMap是线程不安全的
- HashTable允许K,V均可以为null,但是HashMap不能为null,否则会有空指针异常
- 计算Hash的方式不同,HashTable计算哈希的方式是直接取key本身的hash,而HashMap计算hash的方式为:(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16) 自身哈希和哈希无符号右移16位做与运算,之所以会有这种差异是因为HashTable和HashTable计算索引方式不同,HashTable直接与当前长度取余获取当前索引,而HashMap通过公式((size - 1) & hash)计算索引值
- 数据结构不同:HashTable采用的是链表形式,而HashMap采用的是阈值以下用链表阈值以上用红黑树的数据结构
- 存取效率:HashTable的效率相对比较低,因为有synchronized关键字做线程同步,HashMap存取效率比较高,因为没有锁的限制,但因为其不是线程安全的,在线程安全场景下需要进行一些线程同步操作
- 在查询包含关系的时候,HashTable提供的是contains(),containsKey()和containsValue()方法,而hashMap把只有两个分别为:containsKey()和containsValue()
- HashTable是官方建议被替换的以下来自于JDK8中的注释
If a thread-safe implementation is not needed, it is recommended to use
{@link HashMap} in place of {@code Hashtable}. If a thread-safe
highly-concurrent implementation is desired, then it is recommended
to use {@link java.util.concurrent.ConcurrentHashMap} in place of
{@code Hashtable}.
大致含义为:如果你不需要线程同步,建议使用HashMap来代替HashTable,如果你的你是需要线程同步的话使用ConcurrentHashMap来替代Hashtable
网友评论