美文网首页
JDK HashTable详解

JDK HashTable详解

作者: 丑男李狗蛋 | 来源:发表于2017-12-20 15:32 被阅读0次

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

    相关文章

      网友评论

          本文标题:JDK HashTable详解

          本文链接:https://www.haomeiwen.com/subject/rcwwwxtx.html