Class:
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
- Inherited from Abstractmap implements the Map,cloneable,serializable interface
- Can be serialized
- Can be clone
//默认初始容量为16static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16//最大容量static final int MAXIMUM_CAPACITY = 1 << 30//默认扩容因子static final float DEFAULT_LOAD_FACTOR = 0.75f//红黑树转链表的阀值static final int TREEIFY_THRESHOLD = 8;//链表转红黑树阀值static final int UNTREEIFY_THRESHOLD = 6;//存储方式由链表转成红黑树的容量的最小阈值static final int MIN_TREEIFY_CAPACITY = 64;
Initialization
Map<String, Object> map = new HashMap<>();public HashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal load factor: " + loadFactor); this.loadFactor = loadFactor; this.threshold = tableSizeFor(initialCapacity);}
- New Hashmap<> () will enter HashMap (int initialcapacity, float loadfactor) method
- Initialcapacity to 0xB
- Loadfactor defaults to 0.75
- The first step is to determine if the value of initialcapacity is less than 0 or greater than 1 << 30, the second step is to determine if Loadfactor is greater than 0 and whether it is a floating-point number, the third step sets the loadfactor of the instance to 0.75, and the fourth step is 16
Tablesizefor
//返回大于或等于cap且为2的幂的数值static final int tableSizeFor(int cap) { int n = cap - 1; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;}
- Cap-1: If the cap does not subtract the power of the 1,cap=2, the result is twice times the cap and does not match the expected
Hash method
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}
- Hashcode high 16bit with low 16bit participation XOR operation
- Null in NO. 0 place
Node Object
Put method
public V put(K key, V value) { return putVal(hash(key), key, value, false, true);}
Final V putval (int hash, K key, V value, Boolean onlyifabsent, Boolean evict) {node<k,v>[] tab ; Node<k,v> p; int n, I; if (tab = table) = = NULL | | (n = tab.length) = = 0)//capacity expansion, the first expansion length of n = (tab = resize ()). length; (n-1) & hash length must be between the 0-n//(n-1) & hash equals hash% n, and the operation ratio modulo fast//n-1 2 is 01111...,n 2 of the second square if (p = tab[ i = (n-1) & hash]) = = null) tab[i] = NewNode (hash, key, value, NULL); else {node<k,v> E; K K; hash and equals or = phase, replace if (P.hash = = Hash && (k = p.key) = = Key | | (Key! = null && key.equals (k)))) e = p; else if (P instanceof TreeNode)//node is a tree node, add e = ((treenode<k,v>) p) to the red-black tree. Puttreeval (This, tab, hash, key , value); else {//list for (int bincount = 0;; ++bincount) {//Add at end of list if (E = p.next) = = null) {P.next = NewNode (Hash, key, value, NULL); When bincount>=7 is converted to red black tree if (bincount >= treeify_threshold-1)//-1 for 1st Treeifybin (tab, hash); Break }//already exists if (E.hash = = Hash && (k = e.key) = = Key | | (Key! = null && key.equals (k)))) Break Next object p = e; }}//already exists key if (E! = null) {V oldValue = E.value; if (!onlyifabsent | | oldValue = = NULL) E.value = value; Afternodeaccess (e); return oldValue; }} ++modcount; Expansion if (++size > Threshold) resize (); Afternodeinsertion (evict); return null;}
- modulo x 2^n = = x & (2^n-1)
Expansion
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_initi al_capacity) Newthr = oldthr << 1; Double threshold} else if (Oldthr > 0)//initial capacity is placed in threshold Newcap = OLDTHR; else {//Zero initial threshold signifies using defaults 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; if (oldtab! = null) {for (int j = 0; j < Oldcap; ++j) {node<k,v> e; if ((e = oldtab[j])! = null) {OLDTAB[J] = null; if (E.next = = null) 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<k,v> hihead = null, hitail = NULL; Node<k,v> Next; do {next = E.next; if ((E.hash & oldcap) = = 0) {if (Lotail = = null) Lohead = E ; else Lotail.next = e; Lotail = e; } else {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;}
Dry This cup of Java HashMap