美文网首页
HashTable和HashMap的区别

HashTable和HashMap的区别

作者: hu1991die | 来源:发表于2017-10-10 10:30 被阅读73次

    HashTble和HashMap都实现了Map接口,但是它们也有很多区别
    HashTble和HashMap的区别主要的以下几点:

    1、HashTable是线程安全的,因为它的大部分方法使用了Sychronized进行修饰,所以它的方法能够进行同步,从而保证线程安全性,
    HashMap的方法没有使用Sychronized修饰,所以不能保证线程的安全,
    如果HashMap想要保证方法同步,可以使用语句Map map = Collections.sychronizedMap(hashmap),如果是JDK5以上,可以使用CuncurrentHashMap;
    2、HashTable不能存储键值对为null的数据,而HashMap可以;
    3、HashTble和HashMap内部计算hash值的方法不同;
    4、HashTble使用Enumeration迭代器,HashMap使用Iterator迭代器,后者是一种fail-fash迭代器,这种迭代器当集合对象创建了Iterator或者ListIterator后,
    再试图改变集合的话,会抛出ConcurrentModificationException异常;
    5、HashTable中hash数组默认大小是11,增加的方式是old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数
    6、HashTable继承自Dictionary类,而HashMap继承自AbstractMap类;

    HashMap为什么线程不安全

    个人觉得HashMap在并发时可能出现的问题主要是两方面,首先如果多个线程同时使用put方法添加元素,而且假设正好存在两个put的key发生了碰撞(hash值一样),那么根据HashMap的实现,这两个key会添加到数组的同一个位置,这样最终就会发生其中一个线程的put的数据被覆盖。第二就是如果多个线程同时检测到元素个数超过数组大小*loadFactor,这样就会发生多个线程同时对Node数组进行扩容,都在重新计算元素位置以及复制数据,但是最终只有一个线程扩容后的数组会赋给table,也就是说其他线程的都会丢失,并且各自线程put的数据也丢失。

    HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用LinkedList来解决碰撞问题,当发生碰撞了,对象将会储存在LinkedList的下一个节点中。 HashMap在每个LinkedList节点中储存键值对对象。

    当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同一个bucket位置的LinkedList中。键对象的equals()方法用来找到键值对

    HashMap与HashTable的主要区别:

    HashMap和HashTable存在很多的相同点,但是也有几个重要的不同点

    • 1、我们分别查看源码定义可以看出,Hashtable继承自Dictionary基类,而HashMap则是继承自AbstractMap基类。
      Dictionary是任何可将键映射到相应值的类的抽象父类,而AbstractMap则是基于Map接口的骨干实现,以最大限度减少实现此接口所需的工作。

    • 2、HashMap可以允许存在一个为null的key和任意个为null的value,但是Hashtable中的key和value都不允许为null,
      我们查看源码就知道。
      HashMap在进行put操作时,首先会检查key,当遇到key为null时,则会调用putForNullKey()方法来进行处理,而对于value则没有进行任何处理


      image.png

    而Hashtable在进行put操作时,也会首先检查key,当遇到key为null时,则直接会抛出NullPointerException异常信息。


    image.png
    • 3、Hashtable是线程安全的,我们查看源码可以看到其中定义的大部分主要方法都加上了synchronized关键字,而HashMap则没有这样做。

    如果涉及到多线程同步,一般建议使用Hashtable,然后Collections类中还存在一个静态的方法:synchronizedMap(),该方法创建了一个线程安全的Map对象,并把它作为一个封装好的对象返回,如果是jdk1.5版本以上,可以直接使用CurrentHashMap来处理线程同步问题,它的性能相比于其他两个也会更优。

    相关文章

      网友评论

          本文标题: HashTable和HashMap的区别

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