属性

  1. private static final long serialVersionUID = 362498820763181265L;
  2. //初始化容量
  3. static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
  4. static final int MAXIMUM_CAPACITY = 1 << 30;
  5. static final float DEFAULT_LOAD_FACTOR = 0.75f;
  6. //数组转树阈值
  7. static final int TREEIFY_THRESHOLD = 8;
  8. //
  9. static final int UNTREEIFY_THRESHOLD = 6;
  10. //hashtable容量大于64才会数组转红黑树,否则会先扩容数组
  11. static final int MIN_TREEIFY_CAPACITY = 64;
  12. //
  13. transient Node<K,V>[] table;
  14. transient int modCount;
  15. //The next size value at which to resize (capacity * load factor).
  16. int threshold;
  17. final float loadFactor;
  18. transient Set<Map.Entry<K,V>> entrySet;
  19. //The number of key-value mappings contained in this map.
  20. transient int size;

构造方法

  1. //initialCapacity初始化容量
  2. //loadFactor负载因子
  3. //threshold阈值
  4. public HashMap(int initialCapacity, float loadFactor) {
  5. if (initialCapacity < 0)
  6. throw new IllegalArgumentException("Illegal initial capacity: " +
  7. initialCapacity);
  8. if (initialCapacity > MAXIMUM_CAPACITY)
  9. initialCapacity = MAXIMUM_CAPACITY;
  10. if (loadFactor <= 0 || Float.isNaN(loadFactor))
  11. throw new IllegalArgumentException("Illegal load factor: " +
  12. loadFactor);
  13. this.loadFactor = loadFactor;
  14. this.threshold = tableSizeFor(initialCapacity);
  15. }
  16. public HashMap(int initialCapacity) {
  17. this(initialCapacity, DEFAULT_LOAD_FACTOR);
  18. }
  19. public HashMap() {
  20. this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
  21. }
  22. public HashMap(Map<? extends K, ? extends V> m) {
  23. this.loadFactor = DEFAULT_LOAD_FACTOR;
  24. putMapEntries(m, false);
  25. }
  26. //找到大于或等于cap的最小2的幂
  27. //无符号位运算>>>
  28. static final int tableSizeFor(int cap) {
  29. int n = cap - 1;
  30. n |= n >>> 1;
  31. n |= n >>> 2;
  32. n |= n >>> 4;
  33. n |= n >>> 8;
  34. n |= n >>> 16;
  35. return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
  36. }

put方法

  1. public V put(K key, V value) {
  2. return putVal(hash(key), key, value, false, true);
  3. }
  4. static final int hash(Object key) {
  5. int h;
  6. return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
  7. }
  8. final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
  9. boolean evict) {
  10. Node<K,V>[] tab; Node<K,V> p; int n, i;
  11. //如果当前table没有初始化(引用=null并且table长度=0)
  12. if ((tab = table) == null || (n = tab.length) == 0)
  13. //初始化table容量
  14. n = (tab = resize()).length;
  15. //找到要插入元素的table下标,判断为null则直接插入
  16. if ((p = tab[i = (n - 1) & hash]) == null)
  17. tab[i] = newNode(hash, key, value, null);
  18. //否则
  19. else {
  20. //如果hash相同并且key也相同
  21. Node<K,V> e; K k;
  22. if (p.hash == hash &&
  23. ((k = p.key) == key || (key != null && key.equals(k))))
  24. //先用Node<K,V> e保存p
  25. e = p;
  26. //红黑树插入
  27. else if (p instanceof TreeNode)
  28. e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
  29. else {
  30. //数组元素是链表
  31. for (int binCount = 0; ; ++binCount) {
  32. //p.next如果为null,直接插入
  33. if ((e = p.next) == null) {
  34. p.next = newNode(hash, key, value, null);
  35. if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
  36. treeifyBin(tab, hash);
  37. break;
  38. }
  39. //如果哈希碰撞就退出循环
  40. if (e.hash == hash &&
  41. ((k = e.key) == key || (key != null && key.equals(k))))
  42. break;
  43. p = e;
  44. }
  45. }
  46. //处理哈希碰撞
  47. if (e != null) { // existing mapping for key
  48. V oldValue = e.value;
  49. if (!onlyIfAbsent || oldValue == null)
  50. e.value = value;
  51. afterNodeAccess(e);
  52. return oldValue;
  53. }
  54. }
  55. //操作数加一
  56. ++modCount;
  57. //扩容处理
  58. if (++size > threshold)
  59. resize();
  60. afterNodeInsertion(evict);
  61. return null;
  62. }

resize方法

  1. final Node<K,V>[] resize() {
  2. Node<K,V>[] oldTab = table;
  3. int oldCap = (oldTab == null) ? 0 : oldTab.length;
  4. int oldThr = threshold;
  5. int newCap, newThr = 0;
  6. //oldTab只初始化没有数据
  7. if (oldCap > 0) {
  8. if (oldCap >= MAXIMUM_CAPACITY) {
  9. threshold = Integer.MAX_VALUE;
  10. return oldTab;
  11. }
  12. else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
  13. oldCap >= DEFAULT_INITIAL_CAPACITY)
  14. newThr = oldThr << 1; // double threshold
  15. }
  16. else if (oldThr > 0) // initial capacity was placed in threshold
  17. newCap = oldThr;
  18. else { // zero initial threshold signifies using defaults
  19. newCap = DEFAULT_INITIAL_CAPACITY;
  20. newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
  21. }
  22. if (newThr == 0) {
  23. float ft = (float)newCap * loadFactor;
  24. newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
  25. (int)ft : Integer.MAX_VALUE);
  26. }
  27. threshold = newThr;
  28. @SuppressWarnings({"rawtypes","unchecked"})
  29. Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
  30. table = newTab;
  31. //oldTab有数据
  32. if (oldTab != null) {
  33. //扩容,整个数组移动,数组下标是根据数组容量和key的hashcode决定的
  34. for (int j = 0; j < oldCap; ++j) {
  35. Node<K,V> e;
  36. //如果指定下标的数组元素有值,需要先置空
  37. if ((e = oldTab[j]) != null) {
  38. oldTab[j] = null;
  39. //桶只有一个元素则直接存放到数组新下标处的位置
  40. if (e.next == null)
  41. newTab[e.hash & (newCap - 1)] = e;
  42. //如果是树结构
  43. else if (e instanceof TreeNode)
  44. ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
  45. //是链表结构
  46. else { // preserve order
  47. Node<K,V> loHead = null, loTail = null;
  48. Node<K,V> hiHead = null, hiTail = null;
  49. Node<K,V> next;
  50. do {
  51. next = e.next;
  52. //容量扩容2幂次,假设为两倍,数组分为原长度+新增的一倍长度
  53. //在原来位置(低位)
  54. if ((e.hash & oldCap) == 0) {
  55. if (loTail == null)
  56. loHead = e;
  57. else
  58. loTail.next = e;
  59. loTail = e;
  60. }
  61. //数组位置(高位)
  62. else {
  63. if (hiTail == null)
  64. hiHead = e;
  65. else
  66. hiTail.next = e;
  67. hiTail = e;
  68. }
  69. } while ((e = next) != null);
  70. if (loTail != null) {
  71. loTail.next = null;
  72. newTab[j] = loHead;
  73. }
  74. if (hiTail != null) {
  75. hiTail.next = null;
  76. newTab[j + oldCap] = hiHead;
  77. }
  78. }
  79. }
  80. }
  81. }
  82. return newTab;
  83. }