将会从简单到复杂,一步步地实现跟源码一样的HashMap
一:仅使用数组存储
/**
* 一:数组
* 二:数组 + 链表
* 三:数组 + 链表 + resize
* 四:数组 + 链表 + 二叉搜索树
* 五:数组 + 链表 + 红黑树
*/
public class HashMap_my<K,V> {
/**
* 官方源码数组长度默认为16,此处为4,总之为2的N次方就好
*/
Node<K,V>[] elementDate = new Node[4];
class Node<K,V> {
int hash;
K key;
V value;
public Node(int hash, K key, V value) {
this.hash = hash;
this.key = key;
this.value = value;
}
}
public void put(K key,V value) {
int hash = key.hashCode();
/**
* 因为还没使用链表,此处Node还没next属性
*/
final Node<K, V> newNode = new Node<>(hash, key, value);
/**
* 有两种计算索引的方式:
* 1、int index = hash & (elementDate.length - 1)
* 2、int index = hash % elementDate.length
* 当length为2的N次方时,1跟2计算结果是一样的,此处可自行查阅验证
*/
int index = hash % elementDate.length;
elementDate[index] = newNode;
}
public V get(K key) {
int hash = key.hashCode();
int index = hash % elementDate.length;
return elementDate[index].value;
}
public static void main(String[] args) {
final HashMap_my<Object, Object> hashMap = new HashMap_my<>();
hashMap.put("k1","v1");
hashMap.put("k2","v2");
System.out.println(hashMap.get("k1")); // v1
System.out.println(hashMap.get("k2")); // v2
}
}
下面我要对上面代码进行两个优化:
优化1:求hash值
优化2:计算数组下标索引
public class HashMap_my<K,V> {
Node<K,V>[] elementDate = new Node[4];
class Node<K,V> {
int hash;
K key;
V value;
public Node(int hash, K key, V value) {
this.hash = hash;
this.key = key;
this.value = value;
}
}
public void put(K key,V value) {
/**
* 一个int有4字节32位,
* 此处是将hashCode的高16位跟低16位进行异或组成新的低16位,高16位不变
*/
int hash = key.hashCode() ^ (key.hashCode() >>> 16);
final Node<K, V> newNode = new Node<>(hash, key, value);
/**
* hash & (elementDate.length - 1) 与 hash % elementDate.length
* 当length为2的N次方时,1跟2计算结果是一样的
*/
int index = hash & (elementDate.length - 1);
elementDate[index] =