Java--集合--HashMap
- HashMap底层机制及源码剖析
- 理论:
-
源码剖析案例
-
package com.model.map.hashmap; import java.util.HashMap; import java.util.HashSet; /** * @Description:测试类 * @Author: 张紫韩 * @Crete 2021/6/14 20:13 */ public class HashMapDemo01 { public static void main(String[] args) { HashMap<Object, Object> hashMap = new HashMap<>(); hashMap.put("java", "java"); hashMap.put("php", "a"); hashMap.put("java", "JAVA"); System.out.println(hashMap); /** * 1.执行构造器 new HashMap(),初始化加载因子 loadfactor=0.75 ,HashMap$Node[] table=null * public HashMap() { * this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted * } * 2.执行put() * public V put(K key, V value) { * return putVal(hash(key), key, value, false, true); * } * * 2.1 执行hash(key),计算出key的hash值在进行^ (h >>> 16);运算,但会Hash值 * static final int hash(Object key) { * int h; * return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); * } * * 2.2执行key.hashCode(),得到hash值 * public int hashCode() { * int h = hash; * if (h == 0 && value.length > 0) { * char val[] = value; * * for (int i = 0; i < value.length; i++) { * h = 31 * h + val[i]; * } * hash = h; * } * return h; * } * * 3.执行putVal * * final V putVal(int hash, K key, V value, boolean onlyIfAbsent, * boolean evict) { * * //复制变量 * Node<K,V>[] tab; Node<K,V> p; int n, i; * * //判断是否是第一次添加,如果是就之江将table表扩容到16 * if ((tab = table) == null || (n = tab.length) == 0) * n = (tab = resize()).length; * * //通过hash值计算出这个元素应该在表中的那个索引位置,通过索取到这个节点:p * //如果这 节点为 null,直接将这个元素放在这个节点上,否则进入到else中 * if ((p = tab[i = (n - 1) & hash]) == null) * tab[i] = newNode(hash, key, value, null); * else { * * //定义辅助变量 * Node<K,V> e; K k; * * //如果p的hash值和要插入的元素相等,且 两个key == 返回rue或者equals()返回true * //就将 e指向p节点 * if (p.hash == hash && * ((k = p.key) == key || (key != null && key.equals(k)))) * e = p; * * //如果p节点上是一个树,则交给putTreeVal 进行添加此元素 * else if (p instanceof TreeNode) * e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); * else { * * //如果全上面都不满足,则这是一个链表,则进行循环遍历比较 * for (int binCount = 0; ; ++binCount) { * * //p.next==null说明链表中没有和 要添加的元素一样,直接将这个元素放在链表的末尾 * if ((e = p.next) == null) { * p.next = newNode(hash, key, value, null); * * //如果链表长度超过8则进行树化操作 * if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st * * //树化:需要满组表的长度大于等于64且链表的长度大于8,如果节点数量查过8但表的长度为到64,就不进行树化而是先进行扩容 * treeifyBin(tab, hash); * break; * } * * //再循环过程中如果 链表中有一个和 要添加的元素相等(即hash值一样且== 或equals()返回true,则跳出循环不在添加) * if (e.hash == hash && * ((k = e.key) == key || (key != null && key.equals(k)))) * break; * p = e; * } * } * * //进行替换操作, 当跳出上面操作时,e正好是和要添加的元素一样的节点 * if (e != null) { // existing mapping for key * V oldValue = e.value; * if (!onlyIfAbsent || oldValue == null) * * //将链表上的节点e的value替换为 要添加元素的value * e.value = value; * afterNodeAccess(e); * return oldValue; * } * } * * ++modCount; //操作数++ * //节点数量加一,判断节点数量是否超过 了临界值 * if (++size > threshold) * resize(); * afterNodeInsertion(evict); * return null; * } * * * */ } }
-
Hash扩容树华
-
package com.model.map.hashmap; import java.util.HashMap; /** * @Description:测试类 * @Author: 张紫韩 * @Crete 2021/6/15 9:21 */ public class HashMapDemo06 { public static void main(String[] args) { HashMap<Object, Object> hashMap = new HashMap<>(); for (int i = 0; i < 11; i++) { hashMap.put(new ClassA(),"a"); } System.out.println(hashMap); HashMap<Object, Object> hashMap1 = new HashMap<>(); for (int i = 0; i <13; i++) { hashMap1.put(new Integer(i), new Integer(i)); } } } class ClassA{ private String name; @Override public int hashCode() { return 100; } @Override public String toString() { return "ClassA{" + "name='" + name + '\'' + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
-
- 理论: