• Map和Set的详解


      Map和Set是一种专门用来搜素的容器或者数据结构,其搜索的效率与其具体的实例化子类有关,是一种适合动态查找的集合容器

    一、模型

           一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称为Key-Value的键值对 

    因此模型会有两种:

       1、纯Key模型

       2、Key-Value模型

    其中Map中存储的是Key-Value的键值对,Set中只存储了Key

    二、Map的使用

       由此可知:Map是一个接口类,该类没有继承Collection,该类中存储的是结构的键值对,并且K是唯一的,不能重复

      1、Map.Entry的说明

              Map.Entry是Map内部实现的用来存放键值对映射关系的内部类,该类主要提供了的获取

    方法解释
    K.getKey()返回entry中的key
    V.getValue()返回entry中的value
    V.setValue(V value)将键值对中的value替换为指定value

    注: Map.Entry并没有提供设置Key的方法

     2、Map的常用方法

    注:

        (1) Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者HashMap

        (2) Map中存放键值对的Key是唯一的,value是可以重复的

        (3)Map的Key可以全部分离出来,存储到Set中进行访问(因为Key不能重复)

        (4)Map的value可以全部分离出来,存储到Collection中的任意一个子集合中进行访问(因为value不能重复)

        (5)Map中键值对中的Key不能直接修改,value可以修改,如果要修改key,只能先将key删除掉,然后再进行重新插入

        (6)TreeMap和HashMap的区别

    Map底层结构TreeMapHashMap
    底层结构红黑树哈希桶
    插入/删除/查找时间复杂度O(log2^N)O(1)
    是否有序关于key有序无序
    线程安全不安全不安全
    插入/删除/查找区别需要进行元素比较通过哈希函数计算哈希地址
    比较与重写key必须能够比较,否则会抛出ClassCastException异常自定义类型需要重写equals和hashCode方法
    应用场景需要key有序场景下key是否有序不关心,需要更高的时间性能

     3、HashMap的使用案例

    1. public class TestHashMap {
    2. public static void main(String[] args) {
    3. Map hashMap = new HashMap<>();
    4. hashMap.put(1,"hello");
    5. hashMap.put(3,"world");
    6. hashMap.put(20,"world");
    7. hashMap.put(4,"world");
    8. hashMap.put(5,"world");
    9. System.out.println(hashMap);//输出是无序的
    10. System.out.println(hashMap.getOrDefault(100,"啥也没有"));
    11. //按照指定的key获取value
    12. String v1 = hashMap.get(1);
    13. String v5 = hashMap.get(5);
    14. System.out.println(v1);
    15. System.out.println(v5);
    16. }
    17. }

     4、TreeMap的使用案例

    1. import java.util.Collection;
    2. import java.util.Map;
    3. import java.util.Set;
    4. import java.util.TreeMap;
    5. public class TestTreeMap {
    6. //TreeMap的演示,是有序的
    7. public static void main(String[] args) {
    8. TreeMap treeMap = new TreeMap<>();
    9. treeMap.put(1,"hello");
    10. treeMap.put(3,"world");
    11. treeMap.put(2,"world");
    12. treeMap.put(4,"world");
    13. treeMap.put(5,"world");
    14. System.out.println(treeMap);
    15. //按照指定的key获取value
    16. String v1 = treeMap.get(1);
    17. String v5 = treeMap.get(5);
    18. System.out.println(v1);
    19. System.out.println(v5);
    20. String v4 = treeMap.getOrDefault(4,"空值");
    21. String v10 = treeMap.getOrDefault(10,"空值");
    22. System.out.println(v4);
    23. System.out.println(v10);
    24. //删除指定的元素
    25. treeMap.remove(5);
    26. System.out.println(treeMap);
    27. //获取所有的key的不重复集合
    28. Set keySet = treeMap.keySet();
    29. System.out.println(keySet);
    30. //获取所有的value
    31. Collection values = treeMap.values();
    32. System.out.println(values);
    33. //是否包含key,是否包含value
    34. System.out.println(treeMap.containsKey(1));
    35. System.out.println(treeMap.containsValue("hello"));
    36. //遍历
    37. fun1(treeMap);
    38. System.out.println("方法二");
    39. fun2(treeMap);
    40. }
    41. //根据所有的key去获取值,方法一,不常用
    42. private static void fun1(Map map) {
    43. Set keySet = map.keySet();
    44. for (Integer key : keySet) {
    45. System.out.println("key = " + key + " value = " + map.get(key));
    46. }
    47. }
    48. //方法二
    49. private static void fun2(Map map) {
    50. Set> entries = map.entrySet();
    51. for (Map.Entry entry : entries) {
    52. System.out.println("key = " + entry.getKey() + " value = " + entry.getValue());
    53. }
    54. }
    55. }

     

    三、Set的说明

            Set是继承自Collection的接口类,Set只存储了key

     1、常见方法说明

    注:

         (1)Set是继承Collection的一个接口类

         (2) Set只存储了key,并且要求key唯一

         (3)Set底层是使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的

         (4)Set最大的功能就是对集合中的元素进行去重

         (5)实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet,LinkedHashSet是在HashSet的基础上维护了一个双向链表来记录元素的插入次序

         (6)Set的key不能修改,如果要修改,先把原来的删除,再重新插入

         (7)Set不能插入null的key

         (8)TreeSet和HashSet的区别

    Set底层结构TreeSetHashSet
    底层结构红黑树哈希桶
    插入/删除/查找时间复杂度O(log2^N)O(1)
    是否有序关于key有序不一定有序
    线程安全不安全不安全
    插入/删除/查找区别按照红黑树的特性来进行插入和删除先计算key的哈希地址,然后进行插入和删除
    比较与重写key必须能够比较,否则会抛出ClassCastException异常自定义类型需要重写equals和hashCode方法
    应用场景需要key有序场景下key是否有序不关心,需要更高的时间性能

    三、搜索树

         二叉搜索树又被称为二叉排序树,它或者是一颗空树,或者是具有以下性质的二叉树

        若它的左子树不为空,那么左子树上所有的节点的值都小于根节点的值

        若它的右子树不为空,那么右子树上所有的节点的值都大于根节点的值

        它的左右子树也分别为二叉搜索树

     1、删除操作

           设待删除的结点为cur,双亲结点为parent

            (1)cur.left == null

                        cur是root,则root == cur.right

                        cur不是root,cur是parent.left,则parent.left == cur.right

                        cur不是root,cur是parent.right,则parent.right == cur.right

            (2)cur.right == null

                        cur是root,则root == cur.left

                        cur不是root,cur是parent.left,则parent.left == cur.left

                        cur不是root,cur是parent.right,则parent.right == cur.left

            (3)cur.left != null && cur.right != null

                       需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题

      2、实现

    1. public class BinarySearchTree {
    2. private static class TreeNode {
    3. TreeNode left;
    4. TreeNode right;
    5. int val;
    6. public TreeNode(int val) {
    7. this.val = val;
    8. }
    9. }
    10. public TreeNode root;
    11. /**
    12. * 查找指定的值是否存在
    13. * @param val
    14. * @return
    15. */
    16. public boolean search(int val) {
    17. return false;
    18. }
    19. /**
    20. * 插入一个元素
    21. * @param val 要插入的值
    22. * @return
    23. */
    24. public boolean insert(int val) {
    25. TreeNode node = new TreeNode(val);
    26. if (root == null) {
    27. root = node;
    28. return true;
    29. }
    30. TreeNode cur = root;
    31. TreeNode pre = null;
    32. while (cur != null) {
    33. if (val == cur.val) {
    34. return false;
    35. }
    36. pre = cur;
    37. if (val < cur.val) {
    38. cur = cur.left;
    39. } else {
    40. cur = cur.right;
    41. }
    42. }
    43. if (val < pre.val) {
    44. pre.left = node;
    45. } else {
    46. pre.right = node;
    47. }
    48. return true;
    49. }
    50. public boolean remove(int val) {
    51. if (root == null) {
    52. return false;
    53. }
    54. TreeNode cur = root;
    55. TreeNode parent = null;
    56. while (cur != null) {
    57. if (cur.val == val) {
    58. removeNode(parent,cur);
    59. return true;
    60. }
    61. parent = cur;
    62. if (cur.val > val) {
    63. cur = cur.left;
    64. } else {
    65. cur = cur.right;
    66. }
    67. }
    68. return false;
    69. }
    70. private void removeNode(TreeNode parent,TreeNode cur) {
    71. if (cur.left == null) {
    72. if (cur == root) {
    73. root = cur.right;
    74. } else if (cur == parent.left) {
    75. //当前节点是父节点的左孩子节点时
    76. parent.left = cur.right;
    77. } else {
    78. //当前节点是父节点的右孩子节点时
    79. parent.right = cur.right;
    80. }
    81. } else if (cur.right == null) {
    82. if (cur == root) {
    83. root = cur.left;
    84. } else if (cur == parent.left) {
    85. //当前节点是父节点的左孩子节点时
    86. parent.left = cur.left;
    87. } else {
    88. //当前节点是父节点的右孩子节点时
    89. parent.right = cur.left;
    90. }
    91. } else {
    92. TreeNode target = cur.right;
    93. TreeNode parentTarget = cur;
    94. while (target.left != null) {
    95. parentTarget = target;
    96. target = target.left;
    97. }
    98. //到达叶子节点
    99. cur.val = target.val;
    100. //删除target节点
    101. if (target == parentTarget.left) {
    102. parentTarget.left = target.right;
    103. } else {
    104. parentTarget.right = target.right;
    105. }
    106. }
    107. }
    108. public String inorder(TreeNode node) {
    109. StringBuilder sb = new StringBuilder();
    110. if (node == null) {
    111. return sb.toString();
    112. }
    113. String left =inorder(node.left);
    114. sb.append(left);
    115. sb.append(node.val + " ");
    116. String right = inorder(node.right);
    117. sb.append(right);
    118. return sb.toString();
    119. }
    120. public boolean search1(int val) {
    121. if (root == null) {
    122. return false;
    123. }
    124. TreeNode cur = root;
    125. while (cur != null) {
    126. if (val == cur.val) {
    127. return true;
    128. }
    129. if (val < cur.val) {
    130. cur = cur.left;
    131. } else {
    132. cur = cur.right;
    133. }
    134. }
    135. return false;
    136. }
    137. }

    四、练习题加深理解

    1. import java.util.*;
    2. public class Exe_01 {
    3. public static void main(String[] args) {
    4. //生成十万个元素的数组
    5. int capacity = 10000;
    6. int[] arr = new int[capacity];
    7. Random random = new Random();
    8. for (int i = 0;i < arr.length;i++) {
    9. int value = random.nextInt(capacity);
    10. arr[i] = value;
    11. }
    12. fun1(arr);
    13. fun2(arr);
    14. fun3(arr);
    15. }
    16. //去除十万个元素中重复的元素
    17. public static void fun1(int[] arr) {
    18. Set set = new HashSet<>();
    19. for (int i = 0;i < arr.length;i++) {
    20. set.add(arr[i]);
    21. }
    22. System.out.println("去重后元素个数" + set.size());
    23. }
    24. //查找十万个元素中第一次重复的元素
    25. public static void fun2(int[] arr) {
    26. Set set = new HashSet<>();
    27. for (int i = 0;i < arr.length;i++) {
    28. if (!set.contains(arr[i])) {
    29. set.add(arr[i]);
    30. } else {
    31. System.out.println("第一个重复的元素" + arr[i]);
    32. return;
    33. }
    34. }
    35. }
    36. //统计十万个元素中,每个元素出现的次数
    37. public static void fun3(int[] arr) {
    38. Map map = new HashMap<>();
    39. for (int i = 0;i < arr.length;i++) {
    40. int cnt = map.getOrDefault(arr[i],0);
    41. map.put(arr[i],cnt + 1);
    42. }
    43. }
    44. }
  • 相关阅读:
    JavaScript设计模式——命令模式
    在鹅厂工作1到11年的程序媛
    【STM32】MCU HardFault异常处理分析流程及总结(一)
    STM32cubeMX详细教学及多个小项目合集(包含RTOS)
    队列概述以及使用数组模拟实现队列(思路分析) [数据结构][Java]
    国产时序数据库IotDB安装、与SpringBoot集成
    北斗导航 | 格洛纳斯(GLONASS)卫星导航系统
    HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。
    java毕业设计“传情旧物”网站mybatis+源码+调试部署+系统+数据库+lw
    openstack基本命令小结
  • 原文地址:https://blog.csdn.net/m0_53677355/article/details/128065234