一、簡介
1、原理解析
Entry[ ] table 就是HashMap的核心數組結構,我們也稱之爲“位桶數組”;
一個Entry對象存儲了:
-
key:鍵對象 value:值對象
-
next:下一個節點
-
hash: 鍵對象的hash值
顯然每一個Entry對象就是一個單向鏈表結構,我們使用圖形表示一個Entry對象的典型示意:
然後,我們畫出Entry[]數組的結構(這也是HashMap的結構):
存儲過程
2、單個方法原理解析
1、根據key的hash值,確定存儲的位置(取模)
根據key的hash值,取模確定一個值(值小於桶),實現隨機存儲在桶中;
2、存儲元素(key-value)
創建存儲對象,添加值到Node元素對象中,存的過程分爲三種情況。
(1): 獲取的桶元素爲空,直接將當前元素存進去即可;
(2): 遍歷當前桶中元素,如果有相同key,則把value值進行替換;
(3): 遍歷當前桶中元素,如果沒有重複的key,則把值添加到最後;
3、重寫toString方法
創建StringBuilder進行存儲,遍歷桶,再將桶中的鏈表的進行遍歷,取出其中存儲的value的值,進行返回;
4、get方法
根據1、方法獲取key特定的hash值,找到指定的桶,遍歷其中的鏈表,根據key的值,取出value值返回即可。
二、實現的代碼
Node
public class Node<K, V> {
public int hash; //key的hash值
public K key; //key鍵的的值
public V value; //存儲的value值
public Node next; //下一個元素的地址值
}
HashMap
public class MyHashMap<K, V> {
Node[] table; //位桶數組
int size; //存放的鍵值對的個數
public MyHashMap() {
table = new Node[16];
}
public MyHashMap(Node[] table, int size) {
this.table = table;
this.size = size;
}
// 1、根據key的hash值,確定存儲的位置(取模)
private int myHash(int v, int length) {
return v & (length - 1);
}
// 2、存儲元素(key-value)
public void put(K key, V value) {
// -1、創建存儲的對象,並把值放進去
Node newNode = new Node();
newNode.hash = myHash(key.hashCode(), table.length);
newNode.key = key;
newNode.value = value;
newNode.next = null;
// -2、將有值的對象,放進hashMap對象的存儲位置中
Node temp = table[newNode.hash];
Node iterLast = null; //正在遍歷的最後一個元素
boolean keyRepeat = false;
if (temp == null) {
//1、此處數組元素爲空,則直接將節點放進去
table[newNode.hash] = newNode;
size++;
} else {
// 2、此處數組元素不爲空。則遍歷對應鏈表
while (temp != null) {
if (temp.key.equals(key)) {
keyRepeat = true;
temp.value = value; //只是覆蓋value的值即可。其他的(hash,key,next)值保持不變
break;
} else {
// key不重複,則遍歷下一個
iterLast = temp;
temp = temp.next;
}
}
// 3、沒有發生key重複的情況,則添加到鏈表的最後
if (!keyRepeat) {
iterLast.next = newNode;
size++;
}
}
}
// 3、重寫toString方法
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
// 遍歷bucket數組
for (int i = 0; i < table.length; i++) {
Node temp = table[i];
// 遍歷鏈表
while (temp != null) {
sb.append(temp.key + ":" + temp.value);
temp = temp.next;
}
}
sb.setCharAt(sb.length() - 1, '}');
return sb.toString();
}
// 4、get方法
public V get(K key) {
int hash = myHash(key.hashCode(), table.length);
V value = null;
if (table[hash] != null) {
Node temp = table[hash];
while (temp != null) {
// 相等:則說明找到了鍵值對,返回相應的value值
if (key.equals(temp.key)) {
value = (V) temp.value;
break;
} else {
temp = temp.next;
}
}
}
return value;
}
}