Java中的HashMap是一種非常常見的數據結構,可以在O(1)的時間複雜度下進行插入、查找、刪除等操作。本文將從多個方面對Java中HashMap的實現原理進行詳細的闡述。
一、HashMap的概述
HashMap是一種基於哈希表的數據結構,它將鍵映射到值。實現HashMap需要使用hashCode和equals方法,hashCode用於計算鍵的哈希值,equals方法用於比較鍵的值是否相等。HashMap將鍵的哈希值映射到數組的下標,將鍵和值存儲在數組中的相應位置。
HashMap允許null鍵和null值。HashMap不是同步的,因此在並發環境中的操作可能會引發線程安全問題。
下面是HashMap的代碼示例:
public class HashMap extends AbstractMap implements Map, Cloneable, Serializable {
/* HashMap的內部實現 */
}
二、HashMap的主要屬性
HashMap的主要屬性包括:
– capacity:HashMap中的數組容量,默認值為16,必須是2的冪。
– loadFactor:HashMap的裝載因子,默認值為0.75,用於確定何時需要調整HashMap的容量。
– threshold:HashMap的閾值,表示當Hash表中元素個數超過該值,需要進行擴容操作。
– modCount:用於實現迭代器的快速失敗機制。
下面是HashMap的主要屬性的代碼示例:
public class HashMap extends AbstractMap implements Map, Cloneable, Serializable {
/**
* The default initial capacity - MUST be a power of two.
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/**
* The maximum capacity, used if a higher value is implicitly specified
* by either of the constructors with arguments.
* MUST be a power of two <= 1<<30.
*/
static final int MAXIMUM_CAPACITY = 1 << 30;
/**
* The load factor used when none specified in constructor.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/**
* The bin count threshold for using a tree rather than list for a
* bin. Bins are converted to trees when adding an element to a
* bin with at least this many nodes. The value must be greater
* than 2 and should be at least 8 to mesh with assumptions in
* tree removal about conversion back to plain bin.
*/
static final int TREEIFY_THRESHOLD = 8;
/**
* The bin count threshold for untreeifying a (split) bin during a
* resize operation. Should be less than TREEIFY_THRESHOLD, and at
* most 6 to mesh with shrinkage detection under removal.
*/
static final int UNTREEIFY_THRESHOLD = 6;
/**
* The smallest table capacity for which bins may be treeified.
* (Otherwise the table is resized if too many nodes in a bin.)
* Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
* between resizing and treeification thresholds.
*/
static final int MIN_TREEIFY_CAPACITY = 64;
/* HashMap的內部實現 */
}
三、HashMap的哈希算法
HashMap使用哈希算法將鍵值對映射到數組的下標,HashMap使用的哈希算法是JDK官方提供的哈希算法,它將鍵的哈希值右移16位並且與原哈希值進行異或操作,然後將結果作為數組下標。
下面是HashMap的哈希算法的代碼實例:
final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
四、HashMap的底層數據結構
HashMap的底層數據結構是一個數組和一個鏈表。數組的大小為2的n次方,鏈表用來解決哈希衝突。當多個鍵映射到數組的同一個下標時,HashMap會將這些鍵值對保存在同一個鏈表中。當鏈表長度達到8時,鏈表將被轉換為紅黑樹,這樣可以提高查找效率。
下面是HashMap的底層數據結構的代碼示例:
static class Node implements Map.Entry {
final int hash;
final K key;
V value;
Node next;
Node(int hash, K key, V value, Node next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString(){ return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry e = (Map.Entry)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
五、HashMap的代碼示例
下面是一個簡單的HashMap的代碼示例,用於將學生的姓名和成績保存在HashMap中:
import java.util.HashMap;
public class TestHashMap {
public static void main(String[] args) {
HashMap<String, Integer> scores = new HashMap<>();
scores.put("張三", 90);
scores.put("李四", 80);
scores.put("王五", 70);
scores.put("趙六", 60);
for (String name : scores.keySet()) {
System.out.println(name + "的成績為:" + scores.get(name));
}
}
}
輸出結果為:
張三的成績為:90
李四的成績為:80
王五的成績為:70
趙六的成績為:60
六、HashMap的總結
通過本文的介紹,我們了解了Java中HashMap的實現原理,包括它的概述、屬性、哈希算法、底層數據結構以及代碼示例。掌握了HashMap的實現原理,可以幫助我們更好地使用HashMap,在開發中更快地解決問題。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/251726.html