1、hash算法java
// 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
2、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; }
3、HashMap的组成数组
在jdk8之前(不包含jdk8),HashMap是由数组与链表构成,而在jdk8作了改动,当链表的元素大于等于8个时候,则将链表改形成红黑数,目的是为了追求稳定,不管是增删查,他的时间复杂度趋于稳定,都是O(logn)app