什么是Hashmap?


HashMap 是一個關聯數組、哈希表,它是線程不安全的,允許key為null,value為null。遍歷時無序。

在JDK8中,當鏈表長度達到8,會轉化成紅黑樹,以提升它的查詢、插入效率,它實現了Map<K,V>, Cloneable, Serializable接口。

因其底層哈希桶的數據結構是數組,所以也會涉及到擴容的問題。

當HashMap的容量達到threshold域值時,就會觸發擴容。擴容前后,哈希桶的長度一定會是2的次方。
這樣在根據key的hash值尋找對應的哈希桶時,可以用位運算替代取余操作,更加高效。

數組:      內存中的一片連續區域,同類型數據的集合,有索引,查詢快,增刪慢,不可擴容。

鏈表:   不連續的區域,每個節點放值和指向下一個節點的指針。查詢慢,增刪快

哈希表:  可以理解位數組和鏈表的組合。即一個一維數組,但是數組中的每個元素是一個鏈表

HashMap常量:

    1.DEFAULT_INITIAL_CAPACITY    //默認初始化的容量時16,必須是2的冪次方。

    2.MAXIMUM_CAPACITY      //最大容量:最大的容量是2^30。

    3.DEFAULT_LOAD_FACTOR = 0.75f  //默認的負載因子是0.75

    4.TREEIFY_THRESHOLD = 8    //一個桶中bin的存儲方式由鏈表轉換成樹的閾值。即當桶中bin的數量超過TREEIFY_THRESHOLD時使用樹來代替鏈表。默認值是8

    5.UNTREEIFY_THRESHOLD = 6  //當執行resize擴容操作時,當桶中bin的數量少於UNTREEIFY_THRESHOLD時使用鏈表來代替樹。默認值是6 。

    6.MIN_TREEIFY_CAPACITY     //當桶中的bin被樹化時最小的hash表容量

成員變量:

1.transient Node<K,V>[] table; //這個數組在首次使用時初始化,並根據需要調整大小。分配空間時,長度始終是2的冪次方。   

  • table是一個用於存放鍵值對的數組。
  • 第一次使用(插入元素)時被初始化,根據需要可以重新分配空間(擴容: 因為規定容量是2的冪,所以擴容時把原容量乘2.)。
  • 分配的空間長度必須是2的冪次方。

2.transient Set<Map.Entry<K,V>> entrySet;  //當被調用entrySet時被賦值。通過keySet()方法可以得到Map中的key集合,通過values可以得到Map中的value集合。

3.transient int size;    //該值用於存放Map中鍵值對的個數。

4.transient int modCount;  //HashMap被結構性修改的次數

5.int threshold;      //閾值,當HashMap中的鍵值對數量超過了閾值,就會擴容。thresold = capacity * loadFactor

6.final float loadFactor;    //負載因子

 

HashMap共包括4個構造函數:


      public HashMap()// 默認構造函


      public HashMap(int initialCapacity, float loadFactor) / /指定“容量大小”和“加載因子”的構造函數


      public HashMap(int initialCapacity) // 指定“容量大小”的構造函數


      public HashMap(Map<? extends K, ? extends V> m) // 包含“子Map”的構造函數,將m中的全部元素逐個添加到HashMap中

哈希沖突的解決方法:1.開放地址法  2.鏈地址法  3.公共溢出法  4.再哈希法

 

為什么HashMap線程不安全?

HashMap會進行resize操作,在resize操作的時候會造成線程不安全。

1. put的時候導致的多線程數據不一致  

2. HashMap的get操作可能因為resize而引起死循環

HashMap線程不安全應該怎么解決?

1.使用HashTable替代HashMap  //一個線程訪問HashTable的同步方法時,其他線程如果也要訪問同步方法,會被阻塞住。

2.類ConcurrentHashMap定義Map  //ConcurrentHashMap是JUC包中的一個類,方法內部使用了synchronized保證線程安全。

3.Collections類的synchronizedMap(Map m)方法可以返回一個線程安全的Map

 

HashMap跟Hashtable的區別?

HashMap 是 Hashtable 的輕量級實現(非線程安全的實現),他們都完成了 Map 接口,主 要區別在於 HashMap 允許空(null)鍵值(key),由於非線程安全,在只有一個線程訪問 的情況下,效率要高於 Hashtable。

1.歷史原因:Hashtable 是基於陳舊的 Dictionary 類的,HashMap 是 Java 1.2引進的 Map 接口的一個實現

2.同步性:Hashtable 是線程安全的,也就是說是同步的,而 HashMap 是線程序不安全的, 不是同步的

3.值:只有 HashMap 可以讓你將空值作為一個表的條目的 key 或 value


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM