• 数据结构之Map&Set


    文章目录

    • 一、概念、场景及模型
    • 二、Map的使用
      • 1.关于Map的说明
      • 2.关于Map.Entry的说明
      • 3.Map的常用方法
      • 4.Map的遍历方式
      • 5.试题案例
    • Set的使用
      • 1.关于Set的说明
      • 2.试题案例

    c24c7205d0f94659b5d1095dbdca5d0e.png


      一、概念、场景及模型

    Map set是一种专门用来进行搜索的容器或者数据结构,Map和Set是一种适合动态查找的集合容器。TreeMap和TreeSet集合背后的数据结构就是搜索树,红黑树。其中TreeSet底层就是一个TreeMap。
    一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称之为Key-value的键值对,所以模型会有两种:
    1. key 模型
    2. Key-Value 模型
    Map 中存储的就是 key-value 的键值对, Set 中只存储了 Key

    二、Map的使用

    Map的官方文档:Map (Java Platform SE 8 )https://docs.oracle.com/javase/8/docs/api/java/util/Map.html1.关于Map的说明

    Map是一个接口类,该类没有继承自Collection,该类中存储的是结构的键值对,并且K一定是唯一的,不能重复 因为底层是二叉搜索树。
     

    2.关于Map.Entry的说明

    Map.Entry Map 内部实现的用来存放 键值对映射关系的内部类,该内部类中主要提供了的获取,value的设置以及Key的比较方式。
    方法说明
    K getKey()
    返回 entry 中的 key
    V getValue()
    返回 entry 中的 value
    V setValue(V value)
    将键值对中的value替换为指定value
    注意: Map.Entry 并没有提供设置 Key 的方法
     

    3.Map的常用方法

    方法说明
    V get(Object key)
    返回 key 对应的 value
    V getOrDefault(Object key, V defaultValue)
    返回 key 对应的 value,key 不存在,返回默认值
    V put(K key, V value)
    设置 key 对应的 value
    V remove(Object key)
    删除 key 对应的映射关系
    Set keySet()
    返回所有 key 的不重复集合
    Collection values()
    返回所有 value 的可重复集合
    Set> entrySet()
    返回所有的 key-value 映射关系
    boolean containsKey(Object key)
    判断是否包含 key
    boolean containsValue(Object value)
    判断是否包含 value
    注意:
    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的区别
    MapTreeMapHashMap
    底层结构红黑树哈希桶
    插入/删除/查找时间
    复杂度
    O(logN)
    O(1)
    是否有序
    关于Key有序
    无序
    线程安全
    不安全
    不安全
    插入/删除/查找区别
    需要进行元素比较
    通过哈希函数计算哈希地址
    比较与覆写
    key必须能够比较,否则会抛出 ClassCastException异常
    自定义类型需要覆写equals和 hashCode方法
    应用场景
    需要Key有序场景下
    Key是否有序不关心,需要更高的时间性能

    4.Map的遍历方式

    使用最多也最简单的是for循序遍历:

    1. HashMap map = new HashMap<>();
    2. map.put(1,1);
    3. map.put(2,2);
    4. int[] arr = new int[2];
    5. int k = 0;
    6. for (Map.Entry entry:map.entrySet()) {
    7. arr[k++] = entry.getKey();
    8. }

    其实还有使用迭代遍历map、使用keySet迭代遍历map、使用entrySet遍历map这几种方式,但是觉得使用比较麻烦,直接使用for循环比较方便。 

    5.试题案例

    统计10W个数据当中,每个数据出现的次数以及对应的关系。

    1. public static void func3(int[] array) {
    2. HashMap map = new HashMap<>();
    3. //1、遍历原来的数据,统计每个数据出现的次数
    4. for (int i = 0; i < array.length; i++) {
    5. int key = array[i];
    6. if(map.get(key) == null) {
    7. map.put(key,1);
    8. }else {
    9. int val = map.get(key);//key出现的 次数
    10. map.put(key,val+1);
    11. }
    12. }
    13. for (Map.Entry entry: map.entrySet()) {
    14. System.out.println("key: "+entry.getKey()+" 出现了:"+entry.getValue()+"次!");
    15. }
    16. }

    Set的使用

    Set与Map主要的不同有两点:Set是继承自Collection的接口类,Set中只存储了Key。

    Set的官方文档:Set (Java Platform SE 8 )https://docs.oracle.com/javase/8/docs/api/java/util/Set.html1.关于Set的常见方法

    方法说明
    boolean add(E e)
    添加元素,但重复元素不会被添加成功
    void clear()
    清空集合
    boolean contains(Object o)
    判断 o 是否在集合中
    Iterator iterator()
    返回迭代器
    boolean remove(Object o)
    删除集合中的 o
    int size()
    返回set中元素的个数
    boolean isEmpty()
    检测set是否为空,空返回true,否则返回false
    Object[] toArray()
    将set中的元素转换为数组返回
    boolean containsAll(Collection c)
    集合c中的元素是否在set中全部存在,是返回true,否则返回false
    boolean addAll(Collection c)
    将集合c中的元素添加到set中,可以达到去重的效果

    注意:

    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,而Map则可以插入空的key。
     

    2.试题案例

    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

    1. public int singleNumber(int[] nums) {
    2. HashSet set = new HashSet<>();
    3. for (int i = 0; i < nums.length; i++) {
    4. if (!set.contains(nums[i])){
    5. set.add(nums[i]);
    6. }else {
    7. set.remove(nums[i]);
    8. }
    9. }
    10. for (int i = 0; i < nums.length; i++) {
    11. if (set.contains(nums[i])){
    12. return nums[i];
    13. }
    14. }
    15. return -1;
    16. }

     

     

     

  • 相关阅读:
    虚拟机 Workstation 16 Ubuntu22.04 TLS AOSP环境搭建
    如何实现模拟量信号远距离无线传输?
    凉鞋的 Godot 笔记 107. 脚本窗口&文件系统窗口
    LabVIEW中的数据通信方法
    Leetcode笔记——二叉树的迭代遍历
    scala语法(一)(有java基础速学)
    OpenCV(十四):ROI区域截取
    AI二次开发C#图案颜色
    使用子字(subword)构建单词向量的原因分析---学习笔记
    C专家编程 第5章 对链接的思考 5.4 警惕Interpositioning
  • 原文地址:https://blog.csdn.net/crazy_xieyi/article/details/127415258