JDK HashTable详解

先上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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • HashMap 是 Java 面试必考的知识点,面试官从这个小知识点就可以了解我们对 Java 基础的掌握程度。网...
    野狗子嗷嗷嗷阅读 11,681评论 9 107
  • Java8张图 11、字符串不变性 12、equals()方法、hashCode()方法的区别 13、...
    Miley_MOJIE阅读 9,158评论 0 11
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 33,143评论 18 399
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 9,771评论 0 16
  • 千弯百转九天上,连云寺上连云天。 东塘北塘收眼底,庇佑漳河福绵绵。
    迹远留香阅读 4,079评论 0 0

友情链接更多精彩内容