HashMap底层源码详解
package map;
import java.util.HashMap;
/**
-
@Author 雾潋
-
@Version 1.0
*/
public class HashMapSource {
public static void main(String[] args) {
HashMap hashMap = new HashMap();
//1.执行构造器 new HashMap()
// 初始化加载因子loadfactor = 0.75
//HashMap$Node[] table = null
hashMap.put(“java”,10);
//2.执行put调用hash方法,计算key的hash值( h = ke.hashCode() ^ ( h >> 16)
/public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}///3.执行putVal /* final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { HashMap.Node<K,V>[] tab; HashMap.Node<K,V> p; int n, i; //辅助变量 //如果底层的table数组为null,或者 length = 0,就扩容到16 if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //取出hash值对应的索引位置Node, 如果为null,就直接把加入的k -v 创建成 Node,加入该位置 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { HashMap.Node<K,V> e; K k; //辅助变量 //如果table的索引位置的key的hash和新的key的hash值相等 //并满足(table现有的结点的key和准备添加的key是同一个对象 ||equals返回真 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof HashMap.TreeNode) //如果当前的table的有的Node是红黑树,就按照红黑树的方式处理 e = ((HashMap.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); //加入后,判断当前的链表个数,是否已经到8个, 到8个后 //就调用treeBin方法进行红黑树转换 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && //如果在循环比较过程中,发现有相同就break,就只是替换value ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; //替换 key对应的value afterNodeAccess(e); return oldValue; } } ++modCount; //每增加一个Node就size++ if (++size > threshold) //如果size > 临界值就扩容 resize(); afterNodeInsertion(evict); return null; }*/ /*5. 关于树化(转成红黑树) //如果 table 为 null ,或者大小还没有到 64,暂时不树化,而是进行扩容. //否则才会真正的树化 -> 剪枝 final void treeifyBin(Node<K,V>[] tab, int hash) { int n, index; Node<K,V> e; if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) resize(); } */ hashMap.put("php",10); hashMap.put("java",20);
}
}
HashMap源码解释
package map;
import java.util.HashMap;
/**
* @Author 雾潋
* @Version 1.0
*/
public class HashMapSource {
public static void main(String[] args) {
HashMap hashMap = new HashMap();
//1.执行构造器 new HashMap()
// 初始化加载因子loadfactor = 0.75
//HashMap$Node[] table = null
hashMap.put("java",10);
//2.执行put调用hash方法,计算key的hash值( h = ke.hashCode() ^ ( h >> 16)
/*public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}*/
//3.执行putVal
/* final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
HashMap.Node<K,V>[] tab; HashMap.Node<K,V> p; int n, i; //辅助变量
//如果底层的table数组为null,或者 length = 0,就扩容到16
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//取出hash值对应的索引位置Node, 如果为null,就直接把加入的k -v 创建成 Node,加入该位置
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
HashMap.Node<K,V> e; K k; //辅助变量
//如果table的索引位置的key的hash和新的key的hash值相等
//并满足(table现有的结点的key和准备添加的key是同一个对象 ||equals返回真
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof HashMap.TreeNode) //如果当前的table的有的Node是红黑树,就按照红黑树的方式处理
e = ((HashMap.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);
//加入后,判断当前的链表个数,是否已经到8个, 到8个后
//就调用treeBin方法进行红黑树转换
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash && //如果在循环比较过程中,发现有相同就break,就只是替换value
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value; //替换 key对应的value
afterNodeAccess(e);
return oldValue;
}
}
++modCount; //每增加一个Node就size++
if (++size > threshold) //如果size > 临界值就扩容
resize();
afterNodeInsertion(evict);
return null;
}*/
/*5. 关于树化(转成红黑树)
//如果 table 为 null ,或者大小还没有到 64,暂时不树化,而是进行扩容. //否则才会真正的树化 -> 剪枝
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
} */
hashMap.put("php",10);
hashMap.put("java",20);
}
}
HashMap触发扩容、树化模拟
代码
package map;
import java.util.HashMap;
/**
* @Author 雾潋
* @Version 1.0
*/
public class HashMapSource02 {
public static void main(String[] args) {
HashMap hashMap = new HashMap();
for (int i = 0; i <= 12; i++){
hashMap.put(new A(i),"hello");
}
hashMap.put("aaa","bbb");
System.out.println("hashMap:" + hashMap);
}
}
class A {
private int number;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
A a = (A) o;
return number == a.number;
}
@Override
public int hashCode() {
return 100;
}
@Override
public String toString() {
return "A{" +
"number=" + number +
'}' + "\n";
}
public A(int number) {
this.number = number;
}
}