hashmap与hashtable区别

0.继承不同,HashMap继承AbstractMap,HashTable继承Dictionary


1.HashMap是非synchronized的,HashTable则是同步的

由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。


2.HashMap可以接受null(HashMap可以接受为null的键值(key)和值(value) ——其实是第一个原因的果,而Hashtable则不行)。


    public synchronized V put(K key, V value) {
        // Make sure the value is not null
        if (value == null) {
            throw new NullPointerException();
        }


3.HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。这也是第一个原因的果。


4.我们一般对哈希表的散列很自然地会想到用hash值对length取模(即除法散列法),Hashtable中也是这样实现的,这种方法基本能保证元素在哈希表中散列的比较均匀,但取模会用到除法运算,效率很低,HashMap中则通过h&(length-1)的方法来代替取模(要求length为2的n次幂),同样实现了位屏蔽(保证结果小于等于length-1),但效率要高很多,这也是HashMap对Hashtable的一个改进


5.初始容量HashMap 16 HashTable 11;Hashtable 的容量增加逻辑是乘2+1,保证奇数,而HashMap扩容是2倍

(link:史上最详细的Hashtable详解--源码分析



ex:

1.为什么Hashtable ConcurrentHashmap不支持key或者value为null

link:为什么Hashtable ConcurrentHashmap不支持key或者value为null

理解如下:ConcurrentHashmap和Hashtable都是支持并发的,这样会有一个问题,当你通过get(k)获取对应的value时,如果获取到的是null时,你无法判断,它是put(k,v)的时候value为null,还是这个key从来没有做过映射。HashMap是非并发的,可以通过contains(key)来做这个判断。而支持并发的Map在调用m.contains(key)和m.get(key),m可能已经不同了。


2. hashtable的长度为什么是奇数


散列表的长度不能为偶数,why?

因为在将散列码压缩为散列表的索引时,通常是使用取模计算---c%n(c 为散列码,n 为散列表长度)当 n 为偶数时,c%n 的奇偶性与 c 的奇偶性相同,若散列码偏向于奇数或者偶数(内存地址的散列码通常是偶数)这样得到的索引很难是均匀分布的。因此散列表的长度通常取奇数,最好取素数。(link:散列之HashTable学习


3.那为什么hashmap的长度是偶数,如何避免偶数长度带来的问题

实际上 HashMap 也会有此问题,所以 HashMap 会在取模哈希前先做一次哈希,使其包含高位的信息,使散列码均匀奇偶

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

而HashTable:

  int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;


直接用key的hashCode(),不像HashMap里为了增强hash的分散效果而要做二次hash


link:为什么HashTable的默认大小和HashMap不一样?

原文地址:https://www.cnblogs.com/silyvin/p/9106745.html