日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

HashMap和Hashtable的区别总结

發(fā)布時(shí)間:2025/5/22 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HashMap和Hashtable的区别总结 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 前言
  • 源碼分析
    • 繼承關(guān)系的不同:
      • HashMap
      • Hashtable
    • 是否支持鍵值為null不同:
      • HashMap
      • Hashtable
    • 初始化和擴(kuò)容的方式不同:
      • Hashtable
      • HashMap
    • 計(jì)算 hash 值的方法不同:
      • HashTable
      • HashMap
    • 線(xiàn)程安全:
  • 總結(jié)


前言

提示:HashMap和Hashtable是我們常用的兩個(gè)Map集合,我們都知道Hashtable可以保證線(xiàn)程安全,但其實(shí)他們的源碼實(shí)現(xiàn)上野有很多不同的,下面我們就針對(duì)源碼對(duì)HashMap和Hashtable重寫(xiě)做一些研究。


提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

源碼分析

繼承關(guān)系的不同:

HashMap

HashMap 繼承 AbstractMap

public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable

Hashtable

HashTable 繼承 Dictionary

public class Hashtable<K,V>extends Dictionary<K,V>implements Map<K,V>, Cloneable, java.io.Serializable

是否支持鍵值為null不同:

HashMap

HashMap 允許 null 值(key 和 value 都可以)。這樣的鍵只能有一個(gè),可以有一個(gè)或者多個(gè)鍵所對(duì)應(yīng)的值為 null 。

public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;}

Hashtable

Hatable 不允許 null值(key 和 value 都不可以) key為 null 沒(méi)有 hash() ,value 為 null 的時(shí)候報(bào)異常

public synchronized V put(K key, V value) {// Make sure the value is not nullif (value == null) { //value為null拋出NullPointerExceptionthrow 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;}private void addEntry(int hash, K key, V value, int index) {Entry<?,?> tab[] = table;if (count >= threshold) {// Rehash the table if the threshold is exceededrehash();tab = table;hash = key.hashCode();index = (hash & 0x7FFFFFFF) % tab.length;}// Creates the new entry.@SuppressWarnings("unchecked")Entry<K,V> e = (Entry<K,V>) tab[index];tab[index] = new Entry<>(hash, key, value, e);count++;modCount++;}

初始化和擴(kuò)容的方式不同:

Hashtable

public Hashtable() {this(11, 0.75f);//初始容量為11 } public Hashtable(int initialCapacity, float loadFactor) {if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new IllegalArgumentException("Illegal Load: "+loadFactor);if (initialCapacity==0)initialCapacity = 1;this.loadFactor = loadFactor;table = new Entry<?,?>[initialCapacity]; // new 初始化數(shù)組threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1); }

HashMap

HshMap的初始化在上偏文章中做了詳細(xì)介紹這里就好Hashtable()做比較就可以了
HashTable 在構(gòu)造方法里面進(jìn)行初始化,初始化大小為 11 每次擴(kuò)容的時(shí)候變?yōu)樵瓉?lái)的 2n+1 倍
HashMap調(diào)用默認(rèn)構(gòu)造是沒(méi)有初始化的 在第一次 調(diào)用 put 方法的時(shí)候,在 resize() 里面進(jìn)行初始化,初始化大小為 16, 每次擴(kuò)容后,變?yōu)樵瓉?lái)的 2倍

計(jì)算 hash 值的方法不同:

HashTable

public synchronized V put(K key, V value) {// Make sure the value is not nullif (value == null) {throw new NullPointerException();}// Makes sure the key is not already in the hashtable.Entry<?,?> tab[] = table;int hash = key.hashCode(); // 直接調(diào)用算法int index = (hash & 0x7FFFFFFF) % tab.length; // 下標(biāo)計(jì)算@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; }

HashMap

static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); // 計(jì)算得到 } final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {// 這個(gè)方法前面有 }

HashTable:直接調(diào)用 Object 的 hash() 函數(shù),計(jì)算出來(lái) hash 值,下標(biāo)直接 數(shù)組長(zhǎng)度取余得到
? int hash = key.hashCode();
? int index = (hash & 0x7FFFFFFF) % tab.length
Hash Map:首先 高位和低位異或得到 hash 值,然后 再和數(shù)組大小-1 做 與運(yùn)算 得到下標(biāo)
? int hash = key.hashCode() ^ (h >>> 16);
int index = (n - 1) & hash;

線(xiàn)程安全:

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

HashTable的好多方法使用synchronized進(jìn)行加鎖操作保證了線(xiàn)程安全
HashMap 線(xiàn)程不安全

總結(jié)

1、繼承的父類(lèi)不一樣

HashTable :繼承 Dictionary HashMap:繼承AbstractMap

2、線(xiàn)程安全

HashTable:線(xiàn)程安全 HashMap:線(xiàn)程不安全

3、初始化的擴(kuò)容不一樣

HashTable:在構(gòu)造方法里面初始化,初始化大小為 11,每次擴(kuò)容 2n+1 倍 HashMap:在 put 值的時(shí)候進(jìn)行初始化,初始化大小為 16,每次擴(kuò)容 2倍

4、計(jì)算下標(biāo)的方法不同

HashTable:hash值 直接調(diào)用 Object 類(lèi)的HashCode() 方法,計(jì)算下標(biāo)直接對(duì)數(shù)組長(zhǎng)度取余 HashMap:hash值 是通過(guò) 高位和低位異或 得到,下標(biāo)通過(guò) 數(shù)組長(zhǎng)度 和 hash值進(jìn)行與運(yùn)算得到

5、鍵和值 的 null 取值不同

HashTable:鍵和值都不允許為 null HashMap:鍵和值都可以為 null,只能有唯一的鍵值為 null,可以有多個(gè)值為 null

總結(jié)

以上是生活随笔為你收集整理的HashMap和Hashtable的区别总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。