1. Map集合的三个实现类 HashMap、TreeMap、Hashtable
      1. map中的key 无序的 不可重复的 使用set集合存储
      2. map中的value 无序的 可重复的 使用collection集合存储
    2. HashMap 线程不安全的 效率高
      1. JDK7底层使用数组+链表 底层是Entry[]数组 new HashMap时 创建长度为16的数组 每次扩容为当前长度的2倍
      2. JDK8底层使用数组+链表+红黑数 底层是Node[]数组 懒汉式创建 添加元素时才创建长度为16的数组 每次扩容为当前元素的2倍
      3. 当数组的某个下标上的元素>8且数组的长度>64时 此时此下标上的所有数据改为使用红黑数
    3. Hashtable 线程安全的 古老的实现类 效率低
    4. TreeMap 可以对集合进行排序 实现排序遍历 根据Key值进行排序 底层使用红黑树
    5. LinkedHashMap HashMap的子类 保证遍历元素时 按照添加的顺序进行遍历 对于频繁遍历的操作 此类执行效率高于HashMap
    6. properties Hashtable的子类 key与value元素都是String
    1. // 将默认加载因子赋值给loadFactor 0.75f
    2. public HashMap() {
    3. this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    4. }
    1. final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
    2. boolean evict) {
    3. Node<K,V>[] tab; Node<K,V> p; int n, i;
    4. // 将成员变量赋值给局部变量tab 判断是否为空 或长度为0
    5. if ((tab = table) == null || (n = tab.length) == 0)
    6. // resize 创建数组 初始默认长度为16
    7. // n记录数组长度
    8. n = (tab = resize()).length;
    9. // 计算新添加元素应处的位置是否为空 并获取当前位置元素赋值给P
    10. if ((p = tab[i = (n - 1) & hash]) == null)
    11. // 将新添加的元素方法当前位置
    12. tab[i] = newNode(hash, key, value, null);
    13. else {
    14. Node<K,V> e; K k;
    15. // 当前位置元素hash值 key值与新添加元素值相同
    16. if (p.hash == hash &&
    17. ((k = p.key) == key || (key != null && key.equals(k))))
    18. // 将当前元素赋值给e
    19. e = p;
    20. // 红黑树相关处理
    21. else if (p instanceof TreeNode)
    22. e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
    23. else {
    24. // 当前位置元素与新添加元素比对不一致 遍历当前元素链表下的其他元素
    25. for (int binCount = 0; ; ++binCount) {
    26. // 当前元素的下一个元素为空
    27. if ((e = p.next) == null) {
    28. // 将新添加的元素设置为当前元素的下一个元素
    29. p.next = newNode(hash, key, value, null);
    30. // 当前遍历此时>=8-1
    31. if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
    32. // 进入该方法 转换为红黑树或扩容
    33. treeifyBin(tab, hash);
    34. break;
    35. }
    36. // 判断当前e变量的 hash值 key值 是否等于新添加的元素 如果是结束循环
    37. if (e.hash == hash &&
    38. ((k = e.key) == key || (key != null && key.equals(k))))
    39. break;
    40. // 上方的if条件都没能符合条件 将e变量赋值给局部变量p 继续循环
    41. p = e;
    42. }
    43. }
    44. // e不为空
    45. if (e != null) { // existing mapping for key
    46. // 记录当前e变量key的value
    47. V oldValue = e.value;
    48. if (!onlyIfAbsent || oldValue == null)
    49. // 将新添加变量的value赋值e变量(因为key值相同 后添加的覆盖之前的value)
    50. e.value = value;
    51. afterNodeAccess(e);
    52. return oldValue;
    53. }
    54. }
    55. ++modCount;
    56. if (++size > threshold)
    57. resize();
    58. afterNodeInsertion(evict);
    59. return null;
    60. }
    1. final Node<K,V>[] resize() {
    2. // 将成员变量table赋值给新数组
    3. Node<K,V>[] oldTab = table;
    4. // 获取数组长度
    5. int oldCap = (oldTab == null) ? 0 : oldTab.length;
    6. // 获取默认的临界值(数组长度达到临界值 开始扩容) 默认为0
    7. int oldThr = threshold;
    8. int newCap, newThr = 0;
    9. if (oldCap > 0) {
    10. // 数组长度大于默认的最大值
    11. if (oldCap >= MAXIMUM_CAPACITY) {
    12. // 获取integer最大值
    13. threshold = Integer.MAX_VALUE;
    14. return oldTab;
    15. }
    16. // 数组长度小于默认的最大值 并且 大于等于初始容量 扩容原先容量的2倍
    17. else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
    18. oldCap >= DEFAULT_INITIAL_CAPACITY)
    19. newThr = oldThr << 1; // double threshold
    20. }
    21. // 临界值是否大于0
    22. else if (oldThr > 0) // initial capacity was placed in threshold
    23. // 将临界值赋值给变量newCap
    24. newCap = oldThr;
    25. else { // zero initial threshold signifies using defaults
    26. // 临界值为0 获取默认长度
    27. newCap = DEFAULT_INITIAL_CAPACITY;
    28. // 获取临界值 长度*加载因子
    29. newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
    30. }
    31. if (newThr == 0) {
    32. float ft = (float)newCap * loadFactor;
    33. newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
    34. (int)ft : Integer.MAX_VALUE);
    35. }
    36. // 设置临界值
    37. threshold = newThr;
    38. @SuppressWarnings({"rawtypes","unchecked"})
    39. // 创建数组
    40. Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
    41. table = newTab;
    42. if (oldTab != null) {
    43. for (int j = 0; j < oldCap; ++j) {
    44. Node<K,V> e;
    45. if ((e = oldTab[j]) != null) {
    46. oldTab[j] = null;
    47. if (e.next == null)
    48. newTab[e.hash & (newCap - 1)] = e;
    49. else if (e instanceof TreeNode)
    50. ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
    51. else { // preserve order
    52. Node<K,V> loHead = null, loTail = null;
    53. Node<K,V> hiHead = null, hiTail = null;
    54. Node<K,V> next;
    55. do {
    56. next = e.next;
    57. if ((e.hash & oldCap) == 0) {
    58. if (loTail == null)
    59. loHead = e;
    60. else
    61. loTail.next = e;
    62. loTail = e;
    63. }
    64. else {
    65. if (hiTail == null)
    66. hiHead = e;
    67. else
    68. hiTail.next = e;
    69. hiTail = e;
    70. }
    71. } while ((e = next) != null);
    72. if (loTail != null) {
    73. loTail.next = null;
    74. newTab[j] = loHead;
    75. }
    76. if (hiTail != null) {
    77. hiTail.next = null;
    78. newTab[j + oldCap] = hiHead;
    79. }
    80. }
    81. }
    82. }
    83. }
    84. return newTab;
    85. }
    1. /**
    2. * @author:LYY 创建时间:2022/5/7
    3. */
    4. public class MapTest {
    5. public static void main(String[] args) {
    6. HashMap<String, Object> map = new HashMap<>();
    7. map.put("01", "哈哈");
    8. map.put("02", "嘻嘻");
    9. map.put("03", "笨笨");
    10. map.put("04", "嘻嘻");
    11. map.put("04", 55);
    12. System.out.println(map);
    13. // 获取集合中的所有key值
    14. Set<String> keySet = map.keySet();
    15. Iterator<String> iterator = keySet.iterator();
    16. while (iterator.hasNext()) {
    17. System.out.println(iterator.next());
    18. }
    19. // 获取所有value集合
    20. Collection<Object> values = map.values();
    21. for (Object value : values) {
    22. System.out.println(value);
    23. }
    24. // 获取entrySet 遍历所有key和value
    25. Set<Map.Entry<String, Object>> entries = map.entrySet();
    26. Iterator<Map.Entry<String, Object>> iterator1 = entries.iterator();
    27. while (iterator1.hasNext()) {
    28. // 每一个元素可以都是Entry类型数据
    29. Map.Entry<String, Object> next = iterator1.next();
    30. System.out.println(next.getKey() + " == " + next.getValue());
    31. }
    32. }
    33. }