• 一文学懂Map和Set——详解


            Map与Set是一种专门用来搜索的容器或者数据结构,其搜索的效率与具体的实例化子类有关。一般的查找如二分查找,它适合静态类型的查找,即就是不进行插入、删除操作。但现实中,如根据学号查找学生姓名,这种查可能会在查找时进行插入或删除操作,二分查找就不适用了。
            Map就是一个数据对应于另一个数据,如学号与姓名是一一对应的、身份证与某个人是一一对应的
            Set就像是一个集合,它里面存放一组不重复的数据。

    1. Map

    Map底层有HashMap或者TreeMap,主要运用的是HashMap。

    Map有两个变量,就是键值对,下面是Map的初始化

    例如
    1. public class Main{
    2. public static void main(String[] args) {
    3. Map map = new HashMap<>();
    4. map.put("hello",10);
    5. map.put("love",20);
    6. map.put("map",9);
    7. System.out.println(map);
    8. }
    9. }

            输出发现,定义时“hello”在前,“love”在后,但是输出时却先输出“love”,后输出“hello”。

            这是因为存储的时候,是根据一个函数来进行存储的。具体存储在哪里,是由这个函数确定的,这个函数是哈希函数

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

    1.1 Map常用方法

    方法解释
    V get(Object key)返回 key 对应的 value
    V getOrDefault(Object key, V defaultValue)返回 key 对应的 valuekey 不存在,返回默认值
    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)判断是否包含

    1.如keySet()这个函数,作用是返回所有的key,返回值的类型是Set.

    1. public class Main {
    2. public static void main(String[] args) {
    3. Map map = new HashMap<>();
    4. map.put("hello",10);
    5. map.put("love",20);
    6. map.put("map",9);
    7. Set set = map.keySet();
    8. System.out.println(set);
    9. }
    10. }

    输出结果,即就是返回所有的key。

    2.再如entrySet()这个函数,它的返回值是Set>。如:

    Set> set = map.entrySet();

            set的类型是Set>,而set中存放的数据类型是Map.Entry,就是将map中的“键值对”作为一个整体存放的set中,set像是一个大数组,这个类似数组的set中每个值都是map的“键值对”。对于set的输出,可以利用foreach循环进行。

    例如下面代码

    1. public class Main{
    2. public static void main(String[] args) {
    3. Map map = new HashMap<>();
    4. map.put("hello",10);
    5. map.put("love",20);
    6. map.put("map",9);
    7. System.out.println(map);
    8. Set> set = map.entrySet();
    9. for (Map.Entry i:set) {
    10. System.out.println(i.getKey() +" "+ i.getValue() );
    11. }
    12. }
    13. }

    输出结果:

    1.2注意

    1. Map 是一个接口,不能直接实例化对象 ,如果 要实例化对象只能实例化其实现类 TreeMap 或者 HashMap
    2. Map 中存放键值对的 Key 是唯一的, value 是可以重复的
    3. Map 中插入键值对时, key 不能为空,否则就会抛 NullPointerException 异常 ,但是 value 可以为空(针对的是TreeMap
    4. Map 中的 Key 可以全部分离出来,存储到 Set 来进行访问 ( 因为 Key 不能重复 )
    5. Map 中的 value 可以全部分离出来,存储在 Collection 的任何一个子集合中 (value 可能有重复 )
    6. Map 中键值对的 Key 不能直接修改, value 可以修改,如果要修改 key ,只能先将该 key 删除掉,然后再来进行重新插入。

     1.3Map的底层结构

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

    HashMap的时间复杂度为O(1),所以通常情况下,一般使用的是HashMap。

    2. Set

    Set会自动去重

    1. public class Main{
    2. public static void main(String[] args) {
    3. Set set = new HashSet<>();
    4. set.add(1);
    5. set.add(2);
    6. set.add(3);
    7. set.add(1);
    8. System.out.println(set);
    9. }
    10. }

    输出:

    2.1 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 中,可以达到去重的效果

            对于Iterator iterator()函数,返回值类型是Iterator。对于Set的输出,可以利用这个迭代器函数。

    1. public class Main {
    2. public static void main2(String[] args) {
    3. Set set = new HashSet<>();
    4. set.add(1);
    5. set.add(2);
    6. set.add(3);
    7. System.out.println(set);
    8. Iterator iterator = set.iterator();
    9. while(iterator.hasNext()){
    10. System.out.println(iterator.next());
    11. }
    12. }
    13. }

    输出结果:

    2.2 注意

    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 的区别

    2.3 Set的底层结构

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

    一般情况下用的是HashSet

  • 相关阅读:
    PgSQL-执行器机制-Unique算子
    pbootcms模板标签序数从2开始
    CNN和RNN结合与对比,实例讲解
    Nmap渗透测试指南之探索网络
    elasticsearch算法之搜索模型(一)
    17、Flink 之Table API: Table API 支持的操作(1)
    基于Amazon EC2和Amazon Systems Manager Session Manager的堡垒机设计和自动化实现
    IO多路复用--select,poll,epoll
    Spring原理学习(一)容器接口与容器实现
    FlexRay通信协议概述
  • 原文地址:https://blog.csdn.net/m0_57950108/article/details/127722083