1.前言
2.公共方法
3.全局变量&&公共方法
/* * hashmap中同一个桶中的多个节点默认以链表的形式连接,超过一定数量后会以红黑树的形式连接,并将Node转化为TreeNode * 由于TreeNode的大小是Node的两倍,所以当bins(链表)数量下降到一定值的时候会再转化回Node * 术语描述: * table hashmap中存放数据的数组,所有的操作都是以这个table为入口 * hash桶:table数组中的每一个下标位置对应一个hash桶 * bins 同一个桶中的所有子节点集合,也就是node的集合 * Node hash桶中的节点 * */
1 /** 2 * 默认初始化容量,必须是2的指数倍 3 */ 4 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 16 5 6 /** 7 * 最大容量 8 */ 9 static final int MAXIMUM_CAPACITY = 1 << 30; 10 11 /** 12 * 默认的加载因子. 13 */ 14 static final float DEFAULT_LOAD_FACTOR = 0.75f; 15 16 /** 17 * 横向链表bin节点的阈值,超过这个值会进行树化(将链表转化为tree) 18 */ 19 static final int TREEIFY_THRESHOLD = 8; 20 21 /** 22 * 将树化结构转回链表的阈值 23 */ 24 static final int UNTREEIFY_THRESHOLD = 6; 25 26 /** 27 * 触发树化时的表的最小容量,即当链表长度过大时,优先选择扩容,容量超过64之后,才会对链表进行树化 28 */ 29 static final int MIN_TREEIFY_CAPACITY = 64; 30 31 /** 32 * 存储hash entry的数组,第一次使用的时候初始化,在必要的时候进行扩容 33 */ 34 transient Node<K,V>[] table; 35 36 /** 37 * 保存缓存的entry 集合 38 */ 39 transient Set<Map.Entry<K,V>> entrySet; 40 41 /** 42 * 当前map中的entry set的数量(放入的对象的数量) 43 */ 44 transient int size; 45 46 /** 47 * MyHashMap被结构性修改的次数,如:增减map中entry的数量,rehash。 这个字段主要用于iterators遍历时使用,判断是否存在并发操作问题 48 */ 49 transient int modCount; 50 51 /** 52 * 进行扩容的阈值,= (capacity * load factor). 53 */ 54 int threshold; 55 56 /** 57 * 加载因子. 58 */ 59 final float loadFactor;
1 /** 2 * hash值计算 3 */ 4 static final int hash(Object key) { 5 int h; 6 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 7 } 8 9 /** 10 * 返回2的指数倍的数组大小 11 */ 12 static final int tableSizeFor(int cap) { 13 int n = cap - 1; 14 n |= n >>> 1; 15 n |= n >>> 2; 16 n |= n >>> 4; 17 n |= n >>> 8; 18 n |= n >>> 16; 19 return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; 20 } 21 /** 22 *返回hash桶中节点的总数量 23 */ 24 public int size() { 25 return size; 26 } 27 28 /** 29 * 判断hash桶是否为空 30 */ 31 public boolean isEmpty() { 32 return size == 0; 33 }
4.数据结构
/** * bin节点的数据结构 */ static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } public final K getKey() { return key; } public final V getValue() { return value; } public final String toString() { return key + "=" + value; } public final int hashCode() { return Objects.hashCode(key) ^ Objects.hashCode(value); } public final V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; } public final boolean equals(Object o) { if (o == this) return true; if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry<?,?>)o; if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) return true; } return false; } }
5.插入元素
/** * 将对应的key,value放到hashmap中,如果之前存在这个key则直接更新value */ public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } /** * 将一个map添加到当前hashmap中 * @param m 要添加的map * @param evict 当第一次构造这个map时设置为false */ final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) { int s = m.size(); if (s > 0) { if (table == null) { // pre-size //计算 map的capacity float ft = ((float)s / loadFactor) + 1.0F; int t = ((ft < (float)MAXIMUM_CAPACITY) ? (int)ft : MAXIMUM_CAPACITY); if (t > threshold) threshold = tableSizeFor(t); //更新阈值 } else if (s > threshold) resize(); //如果map的大小超过了当前map的阈值,则进行扩容 for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) { K key = e.getKey(); V value = e.getValue(); putVal(hash(key), key, value, false, evict); //遍历当前map,将map中的数据加到当前hashmap中 } } } /** * @param hash key的hash值 * @param key key * @param value value * @param onlyIfAbsent 是否只有不存在这个key的时候才put * @param evict if false, the table is in creation mode. * @return 改key中以前的值,或者null 如果这是第一次添加的话 */ final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; //指向当前的hash数组 Node<K,V> p; //指向当前hash对应桶中的首节点 int n, i; //n表示数组的长度 if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //初始化数组 if ((p = tab[i = (n - 1) & hash]) == null) //判断这个hash所对应的hash桶是否已经有Node节点 tab[i] = newNode(hash, key, value, null); //hash桶中无其它数据,直接在hash桶中添加这个节点即可 else { Node<K,V> e; //保存当前桶中该key对应的数据节点(可能这个key之前插入过) K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) //当前key存在 e = p; else if (p instanceof TreeNode) //当前桶中的节点为tree节点 e = ((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); if (binCount >= TREEIFY_THRESHOLD - 1) // 如果当前桶中的节点数量大于树化阈值,则进行树化 treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // 当前key已经在map中存在,根据入参决定是否更新key的值 V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; //修改modCount,用于iterator判断当前是否存在并发 if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }
/** *将map中的数据放到当前 hashmap中 */ public void putAll(Map<? extends K, ? extends V> m) { putMapEntries(m, true); }
6.获取元素
/** * 返回这个key对应的值 * 找不到这个key或者这个key的值为null时返回null */ public V get(Object key) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value; } /** * 判断当前hashmap中是否有这个key */ public boolean containsKey(Object key) { return getNode(hash(key), key) != null; } /** * 查找方式:先根据hash值找到hash桶,然后遍历hash桶中的Node链表(或者红黑树),找到这个节点 * @param hash key的hash值 * @param key the key * @return the node, or null if none */ final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; //first保存相应hash桶中的第一个节点 int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) { if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }
/** * 判断当前map中是否存在这个值 */ public boolean containsValue(Object value) { Node<K,V>[] tab; V v; if ((tab = table) != null && size > 0) { for (int i = 0; i < tab.length; ++i) { for (Node<K,V> e = tab[i]; e != null; e = e.next) { if ((v = e.value) == value || (value != null && value.equals(v))) return true; } } } return false; }
7.移除元素
/** * 移除指定的节点,返回节点对应的值 */ public V remove(Object key) { Node<K,V> e; return (e = removeNode(hash(key), key, null, false, true)) == null ? null : e.value; } /** * 移除指定的数据,实现方式是在链表中跳过当前节点 * @param matchValue 是否需要匹配值 */ final Node<K,V> removeNode(int hash, Object key, Object value, boolean matchValue, boolean movable) { Node<K,V>[] tab; Node<K,V> p; int n, index; if ((tab = table) != null && (n = tab.length) > 0 && (p = tab[index = (n - 1) & hash]) != null) { Node<K,V> node = null, e; K k; V v; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) node = p; else if ((e = p.next) != null) { if (p instanceof TreeNode) node = ((TreeNode<K,V>)p).getTreeNode(hash, key); else { do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { node = e; break; } p = e; } while ((e = e.next) != null); } } if (node != null && (!matchValue || (v = node.value) == value || (value != null && value.equals(v)))) { if (node instanceof TreeNode) ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable); else if (node == p) tab[index] = node.next; else p.next = node.next; ++modCount; --size; afterNodeRemoval(node); return node; } } return null; }
/** * 清空table中的数据 */ public void clear() { Node<K,V>[] tab; modCount++; if ((tab = table) != null && size > 0) { size = 0; for (int i = 0; i < tab.length; ++i) tab[i] = null; } }
7.扩容
/** * 扩容或者初始化表。 * 扩容是double table,这里注意一个hash一致性问题(2的幂) * @return the table */ final Node<K,V>[] resize() { Node<K,V>[] oldTab = table; int oldCap = (oldTab == null) ? 0 : oldTab.length; int oldThr = threshold; int newCap, newThr = 0; if (oldCap > 0) { //扩容流程 if (oldCap >= MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return oldTab; } else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) newThr = oldThr << 1; // double 扩容table的流程,修改容量值和阈值 } else if (oldThr > 0) // initial capacity was placed in threshold newCap = oldThr; else { // 初始化表的流程,使用默认的初始容量和加载因子 newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); } if (newThr == 0) { float ft = (float)newCap * loadFactor; newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE); } threshold = newThr; @SuppressWarnings({"rawtypes","unchecked"}) Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; //使用数组容量初始化空的数组 table = newTab; //将当前新初始化的空数组置为全局变量 table(hashmap存放node的数组) if (oldTab != null) { //如果这次是扩容操作,需要将原表中的数组拷贝到新的数组中(table) for (int j = 0; j < oldCap; ++j) { Node<K,V> e; if ((e = oldTab[j]) != null) { //遍历处理每一个hash桶 oldTab[j] = null; if (e.next == null) //如果这个hash桶中只有一个节点,则直接将这条链移到相应位置即可 newTab[e.hash & (newCap - 1)] = e; else if (e instanceof TreeNode) //如果子链是树节点,则将树节点进行拆分处理 ((TreeNode<K,V>)e).split(this, newTab, j, oldCap); else { // preserve order Node<K,V> loHead = null, loTail = null; //存放的是要保留在当前桶中的Node节点链表 Node<K,V> hiHead = null, hiTail = null; //存放的是要放在扩容后新产生的桶(j + oldCap)中的链表 Node<K,V> next; do { next = e.next; if ((e.hash & oldCap) == 0) { //根据高位是否为1(扩容正好是2倍扩容,高位为1的话说明hash值会落到新桶中),判断数据迁移 if (loTail == null) loHead = e; else loTail.next = e; loTail = e; } else { //存放要移到新桶中的Node节点链表 if (hiTail == null) hiHead = e; else hiTail.next = e; hiTail = e; } } while ((e = next) != null); if (loTail != null) { loTail.next = null; newTab[j] = loHead; } if (hiTail != null) { hiTail.next = null; newTab[j + oldCap] = hiHead; } } } } } return newTab; }
8. map视图(keyset,valueset,entryset)
/** * 返回当前map中所有key集合的视图 */ public Set<K> keySet() { Set<K> ks = keySet; if (ks == null) { ks = new KeySet(); keySet = ks; } return ks; } /** * hashmap 的key视图 */ final class KeySet extends AbstractSet<K> { public final int size() { return size; } public final void clear() { HashMap_tmp.this.clear(); } public final Iterator<K> iterator() { return new KeyIterator(); } public final boolean contains(Object o) { return containsKey(o); } public final boolean remove(Object key) { return removeNode(hash(key), key, null, false, true) != null; } public final Spliterator<K> spliterator() { return new KeySpliterator<>(HashMap_tmp.this, 0, -1, 0, 0); } public final void forEach(Consumer<? super K> action) { Node<K,V>[] tab; if (action == null) throw new NullPointerException(); if (size > 0 && (tab = table) != null) { int mc = modCount; for (int i = 0; i < tab.length; ++i) { for (Node<K,V> e = tab[i]; e != null; e = e.next) action.accept(e.key); } if (modCount != mc) throw new ConcurrentModificationException(); } } } /** * 返回当前map的values的集合视图 */ public Collection<V> values() { Collection<V> vs = values; if (vs == null) { vs = new Values(); values = vs; } return vs; } /** * hashmap的values视图 */ final class Values extends AbstractCollection<V> { public final int size() { return size; } public final void clear() { HashMap_tmp.this.clear(); } public final Iterator<V> iterator() { return new ValueIterator(); } public final boolean contains(Object o) { return containsValue(o); } public final Spliterator<V> spliterator() { return new ValueSpliterator<>(HashMap_tmp.this, 0, -1, 0, 0); } public final void forEach(Consumer<? super V> action) { Node<K,V>[] tab; if (action == null) throw new NullPointerException(); if (size > 0 && (tab = table) != null) { int mc = modCount; for (int i = 0; i < tab.length; ++i) { for (Node<K,V> e = tab[i]; e != null; e = e.next) action.accept(e.value); } if (modCount != mc) throw new ConcurrentModificationException(); } } } /** * 返回hashmap的key,value视图 */ public Set<Map.Entry<K,V>> entrySet() { Set<Map.Entry<K,V>> es; return (es = entrySet) == null ? (entrySet = new EntrySet()) : es; } /** * hashmap的key value视图 * */ final class EntrySet extends AbstractSet<Map.Entry<K,V>> { public final int size() { return size; } public final void clear() { HashMap_tmp.this.clear(); } public final Iterator<Map.Entry<K,V>> iterator() { return new EntryIterator(); } public final boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<?,?> e = (Map.Entry<?,?>) o; Object key = e.getKey(); Node<K,V> candidate = getNode(hash(key), key); return candidate != null && candidate.equals(e); } public final boolean remove(Object o) { if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry<?,?>) o; Object key = e.getKey(); Object value = e.getValue(); return removeNode(hash(key), key, value, true, true) != null; } return false; } public final Spliterator<Map.Entry<K,V>> spliterator() { return new EntrySpliterator<>(HashMap_tmp.this, 0, -1, 0, 0); } public final void forEach(Consumer<? super Map.Entry<K,V>> action) { Node<K,V>[] tab; if (action == null) throw new NullPointerException(); if (size > 0 && (tab = table) != null) { int mc = modCount; for (int i = 0; i < tab.length; ++i) { for (Node<K,V> e = tab[i]; e != null; e = e.next) action.accept(e); } if (modCount != mc) throw new ConcurrentModificationException(); } } }
9.树化
1 /** 2 * 将Node链表进行树化,前提是满足树化条件(默认是 桶的数量要达到64),否则进行扩容 3 */ 4 final void treeifyBin(Node<K,V>[] tab, int hash) { 5 int n, index; 6 Node<K,V> e; //存放链表的首节点 7 if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) 8 resize(); 9 else if ((e = tab[index = (n - 1) & hash]) != null) { 10 TreeNode<K,V> hd = null, tl = null; //hd存放头节点,tl存放尾节点,建立双向链表 11 do { 12 TreeNode<K,V> p = replacementTreeNode(e, null); //将node转化为TreeNode 13 if (tl == null) 14 hd = p; 15 else { 16 p.prev = tl; 17 tl.next = p; 18 } 19 tl = p; 20 } while ((e = e.next) != null); 21 if ((tab[index] = hd) != null) 22 hd.treeify(tab); 23 } 24 }