Map和Set及其实现类详解

news2024/10/7 10:19:30

目录

一, 搜索

1,传统搜索

2,Map和Set模型

二, Map的使用

1,Map接口的继承及实现图

2,Map接口的使用

3,TreeMap和HashMap的使用和对比

1,TreeMap

代码示例

map中插入的数据按照key进行排序

map中插入的数据必须具有可比较性(或者实现了比较器相关接口)

​map中插入的值必须是唯一的,否则会进行覆盖

​通过Set> entrySet() 方法对map中的键值对进行遍历

将Map中的value全部分离出来存放在Collection中

 

2,HashMap

代码示例

3,TreeMap和HashMap的对比

三, Set的使用

1,Set接口的继承及实现图

2,Set接口的使用

3,TreeSet和HashSet的使用和对比

1,TreeSet

代码示例

Set存入的Key必须是唯一的,存入重复的Key会自动去重

​Set中不能插入为null的数据,否则会报空指针异常的错误

​Set中插入的Key必须具有可比较性

2,HashSet

四, 总结


一, 搜索

1,传统搜索

  • 直接遍历:时间复杂度是O(N),元素如果比较多的情况下效率会非常慢
  • 二分查找:时间复杂度是O(logN),但是搜索的前提是序列必须有序

这两种排序比较适合静态类型的查找(给定区间内的元素进行查找),一般不会对区间上的序列进行插入和删除了,而现实中的查找比如:

  • 根据姓名查找考试成绩
  • 通讯录,根据姓名查询联系方式
  • 不重复集合,需要先搜索关键字是否已经在集合中

这三种在查找时进行一些插入和删除的操作称为动态查找,上述的直接遍历和二分查找的方式就不太适合了,本篇博客介绍的Map和Set集合就是一种专门用来动态查找的集合容器.

2,Map和Set模型

一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称为Key-Value的键值对,所有模型有两种:

  1. 纯Key模型:
    1. 有一个英文词典,快速查找一个单词是否在词典中
    2. 快速查找某个名字在不在通讯录中
  2. Key-Value模型:
    1. 统计文件中每个单词出现的次数,统计结果是每个单词都与其对应的次数:<单词,单词出现的次数>
    2. 梁山好汉的江湖绰号:每个好汉都有自己的江湖绰号

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

二, Map的使用

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

1,Map接口的继承及实现图

  1. Map接口的实现类有两个,分别是TreeMap和HashMap
  2. TreeMap类实现了SortedMap接口(所以TreeMap中存入的key必须是可比较的,后面会说)

2,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<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

注意:

Map接口没有继承Iterable接口,所以使用Map的对象不能直接进行遍历,需要先将其转换成Set对象再进行遍历,Map也提供了相应的方法对这种集合做特殊处理,就是Set<Map.Entry<K, V>> entrySet() 方法,Map.Entry<K, V>是Map内部实现的,用来存放<key,value>键值对映射关系的内部类,该内部类中主要提供了<key,value>的获取,value的设置以及key的比较方式:

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

小结:

  • Map是一个接口,不能直接实例化对象,如果实例化对象只能实例化其实现类TreeMap或者HashMap
  • Map中存放键值对的Key是唯一的,value是可以重复的
  • Map中的Key可以全部分离出来,存储到Set中尽显访问(因为key不能重复,Set要求Key不能重复)
  • Map中的Value可以全部分离出来,存储在Collection的任何一个子集合中
  • Map中键值对的Key不能直接修改,value可以修改,同时存储两个相同的key的键值对时,后存储入Map的会覆盖之前存储入Map中的数据

3,TreeMap和HashMap的使用和对比

1,TreeMap

TreeMap的底层是红黑树(可以把它想象成比较复杂,性能更加优秀的搜索树),我们联想二叉搜索树的一些性能就可以理解TreeMap的一些性能了:

  • 二叉搜索树在插入的时候,对于已经在树中存在的数据是无法进行插入的,所以TreeMap中无法插入两个相同Key值的键值对
  • 二叉搜索树的左子树的数据永远小于相同根节点的右子树的数据,可知他是一棵有序树,TreeMap中的数据也是有序的,所以插入的数据必须具有可比较性,否则会报错(TreeMap是基于Key进行比较的)

代码示例

map中插入的数据按照key进行排序
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("hello",3);
        map.put("abc",4);
        System.out.println(map);
    }

map中插入的数据必须具有可比较性(或者实现了比较器相关接口)
//定义一个Student类 不实现比较器接口
class Student {

}


public static void main(String[] args) {
        Map<Student,Integer> map = new TreeMap<>();
        map.put(new Student(),3);
}
map中插入的值必须是唯一的,否则会进行覆盖
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("hello",3);
        map.put("hello",4);
        System.out.println(map);
    }
通过Set<Map.Entry<K, V>> entrySet() 方法对map中的键值对进行遍历
public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("hello",3);
        map.put("abc",4);
        map.put("def",2);
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        for (Map.Entry<String, Integer> x: entries) {
            System.out.println("key: " + x.getKey() + " 出现了: " + x.getValue() + "次!");
        }
}
将Map中的value全部分离出来存放在Collection中
    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("hello",3);
        map.put("abc",4);
        map.put("def",2);
        Collection<Integer> values = map.values();
        System.out.println(values);
    }

2,HashMap

HashMap的底层是一个哈希桶(数组+链表/红黑树)的结构,查询的时间复杂度是O(1),所以一般HashMap的效率比较高,由于HashMap这个类并没有实现SortedMap这个接口,所以不要求插入的数据中的Key具有可比较性

代码示例

HashMap和TreeMap大部分的方法相同,可以参照TreeMap的代码进行练习,这里只演示HashMap可以插入不需要具有可比较性的数据的代码

class Student {
    
}

public static void main(String[] args) {
        Map<Student,Integer> map = new HashMap<>();
        map.put(new Student(),1);
        map.put(new Student(),2);
        System.out.println(map);
}

3,TreeMap和HashMap的对比

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

三, Set的使用

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

1,Set接口的继承及实现图

  1. Set接口的实现类有两个,分别是TreeSet和HashSet
  2. TreeSet类实现了SortedSet接口,所以TreeSet中存入的key必须是可比较的
  3. Set实现了Iterable接口,所以可以对Set进行遍历

2,Set接口的使用

方法解释
boolean add (E e)
添加元素,但重复元素不会被添加成功
void clear ()
清空集合
boolean contains (Object o)
判断 o 是否在集合中
Iterator<E> 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<? extends
E> c)
将集合 c 中的元素添加到 set 中,可以达到去重的效果

小结:

  • Set是继承自Collection的一个接口类
  • Set中只存储了Key,并且要求Key是唯一的
  • Set的底层是使用Map实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的
  • Set最大的功能就是对集合中的元素进行去重
  • 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet,LinkedHashSet实在HashSet的基础上维护了一个双向链表来记录元素的插入次序
  • Set中的Key不能修改,如果要修改,要先将原来的删除掉,然后再重新插入
  • Set中不能插入null的Key

3,TreeSet和HashSet的使用和对比

1,TreeSet

TreeSet的底层是红黑树(可以把它想象成比较复杂,性能更加优秀的搜索树),我们联想二叉搜索树的一些性能就可以理解TreeSet的一些性能了:

  • 二叉搜索树在插入的时候,对于已经在树中存在的数据是无法进行插入的,所以TreeSet中无法插入两个相同Key
  • 二叉搜索树的左子树的数据永远小于相同根节点的右子树的数据,可知他是一棵有序树,TreeSet中的Key也是有序的,所以插入的数据必须具有可比较性,否则会报错

代码示例

Set存入的Key必须是唯一的,存入重复的Key会自动去重
public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        set.add("hello");
        set.add("abc");
        set.add("abc");
        System.out.println(set);
}
Set中不能插入为null的数据,否则会报空指针异常的错误

    public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        set.add(null);
        System.out.println(set);
    }
Set中插入的Key必须具有可比较性
//定义一个Student类 该类不实现任何比较器接口
class Student {
    
}

public static void main(String[] args) {
        Set<Student> set = new TreeSet<>();
        set.add(new Student());
        System.out.println(set);
}

2,HashSet

HashSet和TreeSet大部分的方法相同,可以参照TreeMap的代码进行练习,这里只演示HashMap可以插入不需要具有可比较性的数据的代码

//定义一个Student类 该类不实现任何比较器接口
class Student {
    
}

public static void main(String[] args) {
        Set<Student> set = new HashSet<>();
        set.add(new Student());
        System.out.println(set);
}

四, 总结

Set和Map使用场景分析:

Set:存储的Key没有其对应的映射关系,且需要对数据进行去重

Map:存储的数据之间存在某种映射关系

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1003115.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙应用开发(基础篇)之列表组件

一、简介 在我们常用的手机应用中&#xff0c;经常会见到一些数据列表&#xff0c;如设置页面、通讯录、商品列表等。下图中两个页面都包含列表&#xff0c;“首页”页面中包含两个网格布局&#xff0c;“商城”页面中包含一个商品列表。 上图中的列表中都包含一系列相同宽度的…

XShell7 + Xftp7 + IDEA 打包MapReduce程序到集群运行

参考博客 【MapReduce打包成jar上传到集群运行】http://t.csdn.cn/2gK1d 【Xshell7/Xftp7 解决强制更新问题】http://t.csdn.cn/rxiBG IDEA打包MapReduce程序 这里的打包是打包整个项目&#xff0c;后期等学会怎么打包单个指定的mapreduce程序再来更新博客。 1、编译打包 …

MATLAB入门-程序控制结构

MATLAB入门-程序控制结构 注&#xff1a;本篇文章为课程学习笔记&#xff0c;课程链接为&#xff1a;头歌 if、elseif、else 相比于C语言&#xff0c;这里多了一个end switch、case、otherwise 相比于C语言&#xff0c;这里也多了一个end&#xff0c;默认字符也不一样。 …

智慧公厕建设,要以技术为支撑、体验为目的、业务为驱动

#智慧公厕[话题]# #智慧公厕系统[话题]# #智慧公厕厂家[话题]# #智慧公厕驿站[话题]# 在数字化城市与智慧城市的大力推进下&#xff0c;作为社会重要的生活设施&#xff0c;智慧化的公共厕所的建设变得越来越重要。作为城市的基础部件之一&#xff0c;公厕的智慧化建设需要进行…

实例 | Python 实现 RSA 加解密

大家好&#xff0c;欢迎来到编程教室 &#xff01; 前阵子看到一篇英文文章[1]&#xff0c;展示了如何用 Python 来实现 RSA 算法。不太熟悉 RSA 的朋友可以看一下一文搞懂 RSA 算法&#xff0c;里面对什么是 RSA&#xff0c;RSA 的数学原理进行了说明&#xff0c;并举了一个简…

平板用的触控笔什么牌子好?开学便宜电容笔推荐

在新学期即将来临之际&#xff0c;你觉得什么样的电容笔才是最好的选择呢&#xff1f;我是一个数码爱好者&#xff0c;有几年以上的使用经验&#xff0c;也知道一些关于电容笔的事情。我觉得&#xff0c;这款苹果原装的电容笔&#xff0c;与普通的电容笔最大的不同之处&#xf…

手把手教你,如何先梳理业务逻辑再写代码

1.业务逻辑与代码 代码是需求逻辑的一种展现形式 需求文档是业务逻辑的一种展现形式&#xff0c;而代码不过是业务逻辑的另一种表现形式&#xff1b;如果逻辑本身有问题&#xff0c;那么它的各种展示形式自然也是错的&#xff0c;所以写代码前应该先思考清楚业务逻辑。 Revi…

【校招VIP】专业课考点之网络存储

考点介绍&#xff1a; cookie、session和localstorage 是目前常用的存储机制&#xff0c;不管是大厂还是中小公司&#xff0c;都会对这个问题有比较高的考察频度&#xff0c;而且有一定的深度和对比分析 专业课考点之网络存储-相关题目及解析内容可点击文章末尾链接查看&#…

为什么C ++在嵌入式系统设计中是C的可行替代品

你是一名。你知道C是适合该工作的语言&#xff0c;尽管有时维护周期可以重复很长时间。有时你会感到that琐&#xff0c;就像在编码自动机一样&#xff0c;反复在结构上创建基本迭代&#xff0c;这些结构与上周或上个月的结构非常相似。 你已经听说过C 作为一种功能强大的语言的…

【AI绘画接口】Midjourney是什么?Midjourney有官方接口吗?

什么是 Midjourney&#xff1f; 随着AI技术的发展&#xff0c;AI聊天、AI绘画都从小众尝鲜逐渐应用到了生产当中。现在市面上的绘画AI并不少&#xff0c;而 Midjourney 是其中最好用的之一。我们只需要输入一些提示词&#xff0c;Midjourney 就能根据输入的提示词自动生成符合…

怎么找回回收站删除的文件?轻松恢复数据,就看这3个方法!

“求助求助&#xff01;回收站删除的文件还有找回来的机会吗&#xff1f;一不小心就把回收站中的文件删除了&#xff0c;现在不知道该如何是好了&#xff0c;希望热心的网友们可以帮帮我&#xff01;” 大家都知道&#xff0c;电脑有一个功能叫回收站&#xff0c;系统会将我们删…

代码随想录 -- day49 -- 121. 买卖股票的最佳时机 、122.买卖股票的最佳时机II

121. 买卖股票的最佳时机 动态规划&#xff1a; dp[i][0] 表示第i天持有股票所得最多现金&#xff0c;dp[i][0] 表示第i天持有股票所得最多现金。 第i-1天就持有股票&#xff0c;那么就保持现状&#xff0c;所得现金就是昨天持有股票的所得现金 即&#xff1a;dp[i - 1][0]第…

echarts折线图每段显示不同的颜色

效果图 配置项&#xff1a; zqChartFour: {title: {text: "一天用电量分布",subtext: "纯属虚构",},tooltip: {trigger: "axis",axisPointer: {type: "cross",},},toolbox: {show: true,feature: {saveAsImage: {},},},xAxis: {type:…

Linux 中nc指令的使用总结

nc指令概述用法一&#xff1a;端口扫描用法二&#xff1a;命令行中发送和接收数据用法三&#xff1a;建立双方通信 nc指令概述 nc 是 Linux 系统中的 netcat 命令之简称&#xff0c;它是一个强大的网络工具&#xff0c;可以用于创建 TCP/UDP 套接字连接。常见的其用法模板可定…

目标检测中生成锚框函数详解

将设一张图片&#xff0c;宽和高为2,2 X torch.rand(size(1,3,2,2)) Y generate_anchors(X,sizes[0.75,0.5,0.25],ratios[1,2,0.5])锚框中心点的设置 # 为每个像素可以生成 nm-1个锚框&#xff0c;整个图像生成 wh(nm-1) def generate_anchors(data,sizes,ratios): # 书上的…

重磅预告 |第十二届中国智能产业高峰论坛9月16日在昌开幕,集团董事长李火亮任专题联席主席,出席本次活动

在这个数字化、智能化社会经济高速迭代的时代&#xff0c;每一次技术的进步都预示着一个全新的未来。在此背景下第十二届中国智能产业高峰论坛即将拉开帷幕。9月16日-9月18日高峰论坛在中国南昌举行&#xff0c;拓世科技集团董事长李火亮将亲身出席本次活动&#xff0c;与众多领…

解决:AD装配输出拾放文件出现闪退问题

PCB在装配输出过程中&#xff0c;需要导出拾放文件&#xff0c;但是今天每次执行这个过程&#xff0c;AD软件就会直接闪退。 重启AD把项目管理器中没有关掉的一系列乱七八糟文件手动关闭关闭AD软件再次重启AD&#xff0c;打开项目重新导出。

YOLOv5 加入SE注意力机制

步骤1&#xff1a;在common.py中添加SE模块 class SE(nn.Module): def __init__(self, c1, c2, r16): super(SE, self).__init__() self.avgpool nn.AdaptiveAvgPool2d(1) self.l1 nn.Linear(c1, c1 // r, biasFalse) self.relu nn.ReL…

付费咨询擅长领域

曾获中国电机工程学报优秀审稿专家&#xff0c;控制与决策审稿专家&#xff0c;系统工程与电子技术审稿专家&#xff0c;计算机科学审稿专家&#xff0c;Mechanical System and Signal Processing审稿专家。 擅长现代信号处理&#xff08;小波分析类&#xff0c;模态分解类&…

SAP 自定义权限对象开发与使用

如何自定义一个权限对象&#xff0c;然后分配到对应的权限角色中&#xff0c;进行用户权限的控制&#xff1f; 具体实现步骤如下&#xff1a; 1. 创建数据元素 进入事务码&#xff1a; SE11 2. 创建权限字段 进入事务码SU20 3. 创建权限对象类以及权限对象 事务码&#xf…