【Map vs Set】:Java数据存储的“双子星”对决

个人主页♡喜欢做梦

欢迎 👍点赞 ➕关注 ❤️收藏 💬评论


目录

🍰一、搜索

🍮1.概念

🍮2.模型

🍰二、Map

🍨1.什么是Map?

🍨2.Map的实例化

🍨3.Map的常见方法

🍨4.Map方法的使用

🍰三、Set

🍯1.什么是Set?

🍯2.Set的常见方法

🍯3.Set方法的使用

🍰四、Map和Set的区别


🍰一、搜索

🍮1.概念

搜索:是指在数据集合过程中查找特定元素或满足特定条件元素的过程。如:在一组数组中查找特定的数字。常见的搜索有直接遍历和二分查找.....

直接遍历和二分查找比较适合静态类型的查找,即一般不会对区间进行插入和删除操作。

所以当需要动态查找时,即查找时要进行一些插入和删除,上述的方法并不适用 。如:在学生系统中,快速查找学生的成绩、统计单词出现的次数、确保用户名唯一(去重)。

Map和Set是一种专门用来进行搜索的容器或者数据结构,是一种适合动态查找的集合容器。

🍮2.模型

一般把搜索的数据称为关键字(key),和关键字对应的称为值(value),所以有两种模型:

  • 1.纯key模型:由唯一的键(key)组成,没有与键直接关联的特定值(value)。

特点:重点在于对键的管理和操作,常用于判断某个元素是否存在。

应用场景:数据去重,黑名单过滤等......

  • 2.key-value模型:是一种键(key)和值(value)进行相关联的数据组织形式。每个键都对应着一个特定的值,通过键可以快速查找、更新与之关联的值。如查找在一串字符串中查找,某个单词在该字符串中出现的次数。

特点:键是唯一的,用于快速定位和访问对应的值,其值可以是各种类型的数据。

应用场景:广泛应用于配置文件、数据库等,比如,以用户ID为键,存储用户姓名等为值。

Set只存储了key,Map存储的就是key---value的键对值。

🍰二、Map

🍨1.什么是Map?

Map是接口类,该类没有继承Collection,储存的是<K,V>结构的键值对,并且K一定是唯一的,不能重复。

🍨2.Map的实例化

Map<K,V>是将键(key)与值(value)进行关联的数据结构,K代表键的类型,V代表值的类型。

Map的实现类主要有HashMap,TreeMap

实例化的实现:

java 复制代码
 public static void main(String[] args) {
        Map<String,Integer> map1=new HashMap<>();
        Map<String,Integer> map2=new TreeMap<>();
    }
  • Map是一个接口,不能直接实例化对象,如果要实例化对象只能通过其实现类TreeMap或者HashMap来实现

🍨3.Map的常见方法

|-------------------------------------------|----------------------------|
| 方法 | 解释 |
| V put(K key,V value) | 设置key值与value值相关联 |
| V remove(Object key) | 将key对应的映射关系删除 |
| V remove(Object key,Object value) | 只有指定的键与指定的值相匹配时才可以删除 |
| V get(Object key) | 返回key对应的value值 |
| V getOrDefault(Object key,V defalutValue) | 返回key对应的value,key不存在,返回默认值 |
| Set<K> keySet() | 返回key中的不重复集合 |
| Collection<V> values() | 返回value的可重复集合 |
| Set<Map.Entry<K,V>> entrySet() | 返回所有的key-value的映射关系 |
| boolean containsKey(Object key) | 判断是否包含key |
| boolean containsValue(Object value) | 判断是否包含value |

🍨4.Map方法的使用

java 复制代码
public static void main(String[] args) {
        Map<String,Integer> map=new HashMap<>();
        //map:设置k,v值
        map.put("a",2);
        map.put("c",5);
        map.put("s",21);
        //get:获取key对应的value值
        System.out.println(map.get("a"));//2
        System.out.println(map.get("b"));//不存在key值,其默认值为null
        //getOrDefault:
        //如果map中有key值,返回key对应的value1值,否则返回设置的默认值
        System.out.println(map.getOrDefault("a",1));//2
        System.out.println(map.getOrDefault("b",3));//3
        //remove1:如果key值与指定的值相匹配,删除;否则,不删除
        map.remove("a",1);//不匹配不删除
        System.out.println(map.get("a"));//a对应的value还是2
        //remove2:删除key对应的value值
        map.remove("a");
        System.out.println(map.get("a"));//null
        //containsKey:判断是否包含key
        System.out.println(map.containsKey("c"));//true
        //containsValue:判断是否包含value值
        System.out.println(map.containsValue(10));//false
        Map<String,Integer> map1=new TreeMap<>();
        map1.put("a",2);
        map1.put("a",3);
        map1.put("b",3);
        map1.put("c",6);
        //Set<K> keySet:返回key中不重复的集合
        Set<String> keySet=map1.keySet();
        System.out.println(keySet);//[a, b, c]
        //Collection<V> values:返回value中可重复的集合
        Collection<Integer> value=map1.values();
        System.out.println(value);//[3, 3, 6]
        //Set<K,V>> entrySet:返回key-value所有的映射关系
        Set<Map.Entry<String,Integer>> entrySet=map1.entrySet();
        System.out.println(entrySet);//[a=3, b=3, c=6]
    }

注意事项:

  • Map中存放键值对的Key是唯一的,value是可重复的,当put相同的key,不同的value值时,只是将key所对应的value值进行替换,以最后存放的value为主;
java 复制代码
public static void main(String[] args) {
    Map<String,Integer> map=new HashMap<>();
    map.put("a",11);
    map.put("a",24);
    map.put("a",15);
    System.out.println(map.get("a"));//15
}
  • 在HashMap中存放的key和value可以都为空,在TreeMap中插入键对值时,key不能为空,value可以为空;

HashMap

java 复制代码
 public static void main(String[] args) {
        Map<String,Integer> map1=new HashMap<>();
        map1.put("a",null);
        map1.get("a");//无异常
        map1.put(null,null);
        map1.get(null);//无异常
    }

TreeMap

java 复制代码
  public static void main(String[] args) {
        Map<String,Integer> map1=new TreeMap<>();
        map1.put("a",null);
        map1.get("a");//无异常
        map1.put(null,2);
        map1.get(null);//报错
    }
  • Map中键值对的key不能直接修改,可以直接修改value值,如果要修改key,只能将key删除,在进行重新插入。
  • HashMap和TreeMap是Map的接口实现类,用于存储键对值数据,以下是他们的区别:

|---------------|-------------------|----------------------------|
| Map的底层结构 | TreeMap | HashMap |
| 底层结构 | 红黑树 | 哈希表(数组+链表/红黑树) |
| 插入/删除/查找时间复杂度 | O(log2N) | O(1) |
| 是否有序 | 关于Key有序 | 无序 |
| 允许null键 | 不允许,需可比较 | 允许null键 |
| 线程安全 | 不安全 | 不安全 |
| 插入/删除/查找区别 | 需要进行元素比较 | 通过哈希函数计算哈希地址 |
| 比较与覆写 | key必须能够比较,否则会抛出异常 | 自定义类型需要覆写equals和hashCode方法 |
| 应用场景 | 需要key有序 | 无序有序,需要更高的时间性能 |

🍰三、Set

🍯1.什么是Set?

Set是一个接口,继承自Collection接口,有HashSet、TreeSet等实现类,HashSet基于哈希表实现,不保证元素有序;TreeSet基于红黑树实现,会对元素进行排序。

🍯2.Set的常见方法

|---------------------------------------|--------------------------------------|
| 方法 | 解释 |
| boolean add(E e) | 添加元素,但元素重复不添加 |
| boolean remove(Object o) | 删除集合中元素o |
| boolean contains(Object o) | 判断o是否包含在集合中 |
| boolean isEmpty() | 检测是否为空,为空返回false,否则返回true |
| void clear() | 清空 |
| Iterator<E> iterator() | 使用迭代器遍历集合中的对象 |
| int size() | 返回set中元素个数 |
| Object[] toArray() | 将set中的元素转换为数组返回 |
| boolean containsAll(Collection<?>c) | 集合中的元素是否在set中的全部存在,是返回true,否则返回false |
| boolean addAll(Collection<? extend) | 将集合c中的元素添加到set中,可以达到去重的效果 |

🍯3.Set方法的使用

java 复制代码
 public static void main(String[] args) {
           public static void main(String[] args) {
        Set<Integer> set1=new HashSet<>();
        //add:添加元素
        set1.add(5);
        set1.add(20);
        set1.add(15);
        set1.add(8);
        //remove:移除元素
        set1.remove(20);
        //是否包含该元素
        System.out.println(set1.contains(5));//true
        System.out.println(set1.contains(2));//false
        //Iterator:遍历集合
        Iterator<Integer> iterator=set1.iterator();
        while(iterator.hasNext()){
            System.out.print(iterator.next()+" ");//5 8 15
        }
        System.out.println();
        //isEmpty:判断是否为空
        System.out.println(set1.isEmpty());//false:不为空
        //size:计算元素个数
        System.out.println(set1.size());//3
        //toArray:将set中的元素转换为数组
        Integer[] toArray=set1.toArray(new Integer[0]);
        for (Integer x:toArray) {
            System.out.print(x+" ");//5 8 15
        }
        System.out.println();
        //containsAll:set是否包含指定集合的所有元素
        Set<Integer> set2=new HashSet<>();
        set2.add(1);
        set2.add(2);
        set2.add(3);
        Set<Integer> set3=new HashSet<>();
        set3.add(1);
        set3.add(2);
        //看set2中是否都包含set3集合中的元素
        boolean containsAll=set2.containsAll(set3);
        System.out.println(containsAll);//true
        //addAll:将集合中的元素添加到set中
        Set<Integer> set4=new TreeSet<>();
        set4.add(1);
        set4.add(5);
        set4.add(19);
        Set<Integer> set5=new TreeSet<>();
        set5.add(2);
        set5.add(1);
        set5.add(6);
        boolean addAll=set4.addAll(set5);
        Iterator<Integer> iterator1=set4.iterator();
        while(iterator1.hasNext()){
            //如果是HashSet那么不自动排序,如果是TreeSet就自动排序
            System.out.print(iterator1.next()+" ");//1 2 5 6 19
        }

注意:

  • Set只存储了key,并且要求key一定要唯一,其key值不能进行修改,如果要进行修改需要删除后再插入。
  • Set可以对集合进行去重;
  • TreeSet的底层是使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中;
  • TreeSet和HashSet的区别

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

🍰四、Map和Set的区别

|------|---------------------|---------------------------|
| 区别 | Map | Set |
| 存储形式 | 是一种键对值(key-value)集合 | 是值的集合,值存在单一的值,不存在重复元素 |
| 访问方式 | get(key)方法 | 没有键对值的映射,一般通过for循环或者迭代器遍历 |
| 唯一性 | 键是唯一的,不用重复,值可以重复 | 所有元素都是唯一的 |
| 应用场景 | 需要建立映射关系的场景 | 需要确保元素唯一的场景 |


相关推荐
Dizzy.51718 分钟前
数据结构(查找)
数据结构·学习·算法
Jared_devin3 小时前
数据结构——模拟栈例题B3619
数据结构
sushang~4 小时前
leetcode21.合并两个有序链表
数据结构·链表
sjsjs115 小时前
【数据结构-并查集】力扣1202. 交换字符串中的元素
数据结构·leetcode·并查集
WYF_1115016 小时前
数据结构——单向循环链表、双链表、双向循环链表
数据结构
没有不重的名么9 小时前
MATLAB基础学习相关知识
数据结构·学习·matlab
ll77881110 小时前
LeetCode每日精进:225.用队列实现栈
c语言·开发语言·数据结构·算法·leetcode·职场和发展
ん贤11 小时前
蓝桥杯学习大纲
数据结构·算法
天若有情67311 小时前
【数据结构】C++实现链表数据结构
数据结构·c++·链表
skaiuijing13 小时前
buf存储器缓存
网络·数据结构