HashMap:HashMap学习笔记
2019-08-01 07:17
1636 查看
一、hash算法
// jdk中hash方法 static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } // hashMap中执行putVal的方法,截取一小段 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); 例如: // 取hash值,并转换为二进制 int h = "test".hashCode(); System.out.println(Integer.toBinaryString(h)); // 将hash值右移16位 int nh = h >>> 16; System.out.println(Integer.toBinaryString(nh)); // 获得h与nh的异或的值 int hash = h ^ nh; System.out.println(Integer.toBinaryString(hash)); 输出 1101100100010010010010 110110 1101100100010010100100 32位补全整理之后 hashCode 0000 0000 0011 0110 0100 0100 1001 0010 右移16位后 0000 0000 0000 0000 0000 0000 0011 0110 前面两个值异或 0000 0000 0011 0110 0100 0100 1010 0100
- 先将传入的值取hashCode值,记作h
- 再将h右移16位,记作nh
- 最后将h与nh进行异或就是最终结果hash
- 将hash与15相与(即取模)获得索引位置index
二、Java8 HashMap存入的源码注释
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; // 判断当前数组是否已经进行了初始化 // tab是当前Node数组 if ((tab = table) == null || (n = tab.length) == 0) // 如果没有初始化,则初始化,扩充数组 n = (tab = resize()).length; // 表示当前index位置没有存储位置 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); // 表示索引的坑位被占用 else { HashMap.Node<K,V> e; K k; // 判断当前的key是否存在,如果存在,则覆盖 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; // 判断是否是红黑树,则往树里插入元素 else if (p instanceof HashMap.TreeNode) 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,则将链表转换成红黑树 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } // 如果有重复元素,则跳出 if (e.hash == hash && ((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; afterNodeAccess(e); return oldValue; } } // 迭代器 failfast 快速失败 ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }
三、HashMap的组成
在jdk8以前(不包含jdk8),HashMap是由数组与链表构成,而在jdk8做了改动,当链表的元素大于等于8个时候,则将链表改造成红黑数,目的是为了追求稳定,无论是增删查,他的时间复杂度趋于稳定,都是O(logn)
相关文章推荐
- Java HashMap学习笔记
- JDK源码学习笔记——HashMap
- 集合Map,HashMap、TreeMap+JAVA学习笔记-DAY18
- Java学习笔记之HashMap和Hashtable的区别
- HashMap实现原理分析(转自 Alpha's 学习笔记 )
- Java300学习笔记(19)—— 引用(强软虚弱),WakeHashMap,IdentityHashMap 与 EnumMap
- java学习笔记——HashMap的泛型容器
- Java学习笔记之集合(八):HashMap的存储原理
- stl源码剖析 详细学习笔记 hashset hashmap
- 0017 Java学习笔记-集合-集合一般:HashSet和HashMap
- stl源码剖析 详细学习笔记 hashset hashmap
- HashMap和Hashtable的区别 ---学习笔记
- HashMap学习笔记,比较JDK1.7/1.8的区别
- HashMap和Hashtable的区别 ---学习笔记
- 学习笔记--HashMap浅析
- Java学习笔记:Map集合-HashMap和HashTable(01)
- Java集合源码学习笔记(五)ArrayList,LinkedList,Vector和Hashtable,HashMap的比较
- 基于jdk1.8的HashMap源码学习笔记
- HashMap学习笔记
- Java 学习笔记 05 HashMap 和 Hashtable 区别与联系