必威体育Betway必威体育官网
当前位置:首页 > IT技术

JDK1.8 --- HashTable和HashMap的区别

时间:2019-09-04 01:42:14来源:IT技术作者:seo实验室小编阅读:61次「手机版」
 

hashtable

HashTable从实现角度和HashMap大致相同。

不同的有以下几点:

HashTable不允许key和value为null,HashMap允许key和value为null。

 /**
  * Maps the specified <code>key</code> to the specified
  * <code>value</code> in this hashtable. Neither the key nor the
  * value can be <code>null</code>. <p>
  *
  * The value can be retrieved by calling the <code>get</code> method
  * with a key that is equal to the original key.
  *
  * @param      key     the hashtable key
  * @param      value   the value
  * @return     the previous value of the specified key in this hashtable,
  *             or <code>null</code> if it did not have one
  * @exception  NullPointerException  if the key or value is
  *               <code>null</code>
  * @see     Object#equals(Object)
  * @see     #get(Object)
  */
 public synchronized V put(K key, V value) {
     // Make sure the value is not null
     if (value == null) {
         throw new NullPointerException();
     }

     // Makes sure the key is not already in the hashtable.
     Entry<?,?> tab[] = table;
     int hash = key.hashCode();
     int index = (hash & 0x7FFFFFFF) % tab.length;
     @SuppressWarnings("unchecked")
     Entry<K,V> entry = (Entry<K,V>)tab[index];
     for(; entry != null ; entry = entry.next) {
         if ((entry.hash == hash) && entry.key.equals(key)) {
             V old = entry.value;
             entry.value = value;
             return old;
         }
     }

     addEntry(hash, key, value, index);
     return null;
 }

如果value == null 直接抛出空指针异常;

int hash = key.hashCode(); 调用key的hashCode()方法,所以key也不允许为null。

Hashtable是线程安全的,HashMap是线程不安全的。

因为方法上加了同步synchronized。

Hashtable的初始容量与HashMap不同。


/**
 * Constructs a new, empty hashtable with a default initial capacity (11)
 * and load factor (0.75).
 */
public Hashtable() {
    this(11, 0.75f);
}

Hashtable的初始容量为11,HashMap的初始容量是16。

Hashtable计算和定位索引的方式和HashMap不同

Hashtable在定位索引的时候使用key自己的hashCode方法。没有像HashMap一样去做扰动,得到hash值之后与int最大值(0x7FFFFFFF),然后用结果对容量求余

HashMap在定位索引的时候使用自己实现的hash方法,先求key的hashCode然后高低位做异或扰动,然后与容量做运算。

Hashtable的扩容方式和HashMap不同

/**
 1. Increases the capacity of and internally reorganizes this
 2. hashtable, in order to accommodate and access its entries more
 3. efficiently.  This method is called automatically when the
 4. number of keys in the hashtable exceeds this hashtable's capacity
 5. and load factor.
  */
 @SuppressWarnings("unchecked")
 protected void rehash() {
     int oldCapacity = table.length;
     Entry<?,?>[] oldMap = table;

     // overflow-conscious code
     int newCapacity = (oldCapacity << 1) + 1;
     if (newCapacity - MAX_ARRAY_SIZE > 0) {
         if (oldCapacity == MAX_ARRAY_SIZE)
             // Keep running with MAX_ARRAY_SIZE buckets
             return;
         newCapacity = MAX_ARRAY_SIZE;
     }
     Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];

     modCount++;
     threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
     table = newMap;

     for (int i = oldCapacity ; i-- > 0 ;) {
         for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
             Entry<K,V> e = old;
             old = old.next;

             int index = (e.hash & 0x7FFFFFFF) % newCapacity;
             e.next = (Entry<K,V>)newMap[index];
             newMap[index] = e;
         }
     }
 }
  1. 从上面代码可以看出Hashtable扩容之后的容量是原容量的两倍加1。HashMap扩容之后的容量是原容量的两倍。

    这个区别的原因,需要从他们的初始容量说起:HashMap的容量要求必须为2的幂次方,是因为定位索引的方式,2的幂次方的容量能够是的索引值平均分布。。所以在扩容是每次都以两倍的方式。

    而Hashtable定位是通过求余的方式定位,那对什么数求余能最大程度的均匀分布呢?答案是素数(质数)[参考:https://blog.csdn.net/majinggogogo/article/details/80260539],所以Hashtable在扩容的时候也必须保证扩容之后的数也为素数,所以就在乘以2的前提下再加了1。

    但是,hashtable并没有强制保证容量一定是是质数,因为可以通过初始化或者,putAll的方式调整容量,这可能是HashTable已经不被sun公司推荐使用了。

  2. 扩容方式:hashtable实现比较简单,只是简单的对元素头节点做再次hash,重新分布,不像HashMap会对之后的节点做再次分布,所以对于Hashtable而言扩容之后不会改善hash表的冲突状况。

HashTable的数据结构和HashMap稍有不同

前面博客提到,HashMap在链表冲突元素达到8个以上时会转化为红黑树,这个是为了查找速度考虑,Hashtable没有这样的策略。

HashMap继承了AbstractMap,HashTable继承Dictionary抽象类,两者均实现Map接口。

总结:HashMap不能在并发的环境使用,而HashTable不推荐在并发的环境使用,因为Hashtable锁的粒度太大,在并发环境推荐使用 ConcurrentHashMap。

相关阅读

js事件绑定的几种方式与on()、bind()的区别

一直不是很理解几种js事件绑定之间的区别与联系,今天百度了一下,在此做一总结:1.如果只是简单的绑定一个事件,可以直接写在行内,点击执

HTML中cellpadding与cellspacing的区别解析

单元格(cell) -- 表格的内容单元格边距(表格填充)(cellpadding) -- 代表单元格外面的一个距离,用于隔开单元格与单元格空间单元格

32位和64位程序的区别

转自:https://blog.csdn.net/nma_123456/article/details/45077345 由于操作系统内存分配的不同,导致软

品牌和Logo的区别,你真的清楚吗?

Logo是品牌落地的一种外在形式,品牌的学问太多了,我在最近的几个项目中都有很深的体会。不管是前期的风格尝试,情绪版,还是后面落地到

paddingLeft 与 layout_marginLeft 的区别

paddingleft(内边距) 是指对其内部内容的内边距 layout_marginLeft (外边距)是指距离外部的容器的距离 该图片中的第一个是加上  an

分享到:

栏目导航

推荐阅读

热门阅读