Java Map和Set
目录
- 1. 二叉排序树(二叉搜索树)
- 1.1 二叉搜索树的查找
- 1.2 二叉搜索树的插入
- 1.3 二叉搜索树的删除(7种情况)
- 1.4 二叉搜索树和TreeMap、TreeSet的关系
- 2. Map和Set的区别与联系
- 2.1 从接口框架的角度分析
- 2.2 从存储的模型角度分析【2种模型】
- 3. 关于Map
- 3.1 Map的注意事项
- 3.2 TreeMap 和 HashMap的对比
- 3.3 Map.Entry<k,v>的用法 (遍历)
- 4. 关于Set
- 4.1 Set的注意事项
- 4.2 TreeSet 和 HashSet的对比
- 4.3 迭代器遍历Set
- 5. 哈希表
- 5.1 哈希函数
- 5.2 冲突
- 5.3 冲突的解决:开放地址法和链地址法
- 5.4 哈希表与Java集合类的关系
- 6. HashMap源码分析
- 6.1 成员变量
- 6.2 构造方法
- 6.3 put方法源码
1. 二叉排序树(二叉搜索树)
二叉搜索树又称二叉排序树
- 若左子树不为空,则左子树上所有节点的值都小于根节点的值
- 若右子树不为空,则右子树上所有节点的值都大于根节点的值
- 左右子树也分别是二叉搜索树
【左小右大】
1.1 二叉搜索树的查找
【二叉搜索树的查找,一般情况下一次可以干掉很多数据】
为了保证每次可以干掉很多数据
思路:取遍历节点为cur,每次要查找的值val和cur的val进行比较,如果要查找的值比cur的val小,则去cur的左边继续查找,如果大则去cur的右边继续查找。
public boolean search(int val) {TreeNode cur = root;while (cur != null) {if (cur.val == val) {return true;}else if (cur.val > val) {cur = cur.left;}else {cur = cur.right;}}return false;}
1.2 二叉搜索树的插入
思路:整体思路与查找的思路类似,但是二叉搜索树的每次插入的节点一定是叶子节点,因此需要记录待插入节点的双亲。
当cur为空时,parent记录了待插入结点的父亲位置,再用val和parent的val比较进行插入。
public void insert (int val) {Node node = new Node(val);if (root == null) {root = node;return;}Node cur = root;Node parent = root;while (cur != null) {if (cur.val == val) {return;}else if (cur.val > val) {parent = cur;cur = cur.left;}else {parent = cur;cur = cur.right;}}if (parent.val > val) {parent.left = node;}else {parent.right = node;}}
1.3 二叉搜索树的删除(7种情况)
设待删除结点为cur,待删除结点的双亲结点为parent
整体看分以下3种大情况:
①cur的左为空
②cur的右为空
③cur的左和右都不为空
继续细分:cur是不是root;cur不是root的话,是parent的左还是parent的右
故有3 + 3 + 1 = 7种情况。
- 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; - 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; - cur.left != null && cur.right != null
此时需要使用替换法进行删除,即在它的右子树种寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题。1.4 二叉搜索树和TreeMap、TreeSet的关系
TreeMap和TreeSet是Java种利用搜索树实现的Map和Set,实际上用的是红黑树,红黑树是一颗近似平衡的二叉搜索树,即在二叉搜索树的基础之上+颜色以及红黑树性质。
2. Map和Set的区别与联系
2.1 从接口框架的角度分析

Map是一个独立的接口,而Set继承自Collection接口。
TreeMap 和 TreeSet 都继承了一个Sorted接口,说明 Tree某某 都是经过排序的,即 Tree某某 都是关于key有序的。
2.2 从存储的模型角度分析【2种模型】
- Map中存储的是键值对key-value
- Set中只存储了key
3. 关于Map
Map是一个接口类,该类没有继承collection,该类中存储的是<k,v>结构的键值对,并且k一定是唯一的,不能重复。
3.1 Map的注意事项
- Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者HashMap。
Map<Integer, Integer> map1 = new HashMap<>();Map<Integer, Integer> map2 = new TreeMap<>();
- Map中存放键值对的键key是唯一的,key不可以重复,但是value可以重复。
- 在TreeMap中插入键值队的时候,key不能为空,否则会抛出NPE(空指针异常),但是value可以为空,因为TreeMap中的key是要进行比较的;反而HashMap的key和value都可以为空,因为HashMap不涉及比较。
- Map中的key可以全部分离出来,存储到Set中进行访问(因为key不能重复,set是天然的去重),Map中的value可以全部分离出来,存储到Collection的任何一个子集合中(value可能有重复)
3.2 TreeMap 和 HashMap的对比
| Map底层结构 | TreeMap | HashMap |
|---|---|---|
| 底层结构 | 红黑树 | 哈希桶 |
| 插入/删除/查找时间复杂度 | O(log2N) | O(1) |
| 是否有序 | 关于key有序 | 无序 |
| 线程安全 | 不安全 | 不安全 |
| 插入/删除/查找区别 | 需要进行元素比较 | 通过哈希函数计算哈希地址 |
| 比较与覆写 | key必须能够比较,否则会抛出类型转换异常 | 自定义类型需要覆写equals和hashcode方法 |
| 应用场景 | 需要key有序的场景下 | key是否有序不关心,需要更高的时间性能 |
3.3 Map.Entry<k,v>的用法 (遍历)
Set<Map.Entry <k,v>> entrySet(), 返回所有的key-value映射关系

Map<Integer, Integer> map = new TreeMap<>();map.put(1,2);map.put(2,3);map.put(3,6);//key一定是可以进行比较的for(Map.Entry<Integer,Integer> entry : map.entrySet()) {System.out.println(entry.getKey() + ":" + entry.getValue());}
分析:
打印所有的键值对
entrySet():将Map中的键值对放在Set中返回了。

4. 关于Set
Set与Map主要的不同有2点:
①Set是继承自Collection的接口类
②Set中只存储了Key
Map不能使用迭代器遍历,但是Set可以,因为Set实现了Iterable接口
4.1 Set的注意事项
-
Set是继承自Collection的一个接口类
-
Set中只存储了key,并且要求key一定要唯一
-
Set的底层使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中

-
Set最大的功能就是对集合中的元素进行去重
-
TreeSet中不能插入null的key,但是HashSet可以
4.2 TreeSet 和 HashSet的对比
| Set底层结构 | TreeSet | HashSet |
|---|---|---|
| 底层结构 | 红黑树 | 哈希桶 |
| 插入/删除/查找时间复杂度 | O(log2N) | O(1) |
| 是否有序 | 关于key有序 | 不一定有序 |
| 线程安全 | 不安全 | 不安全 |
| 插入/删除/查找区别 | 按照红黑树的特性进行插入和删除 | 通过哈希函数计算哈希地址 |
| 比较与覆写 | key必须能够比较,否则会抛出类型转换异常 | 自定义类型需要覆写equals和hashcode方法 |
| 应用场景 | 需要key有序的场景下 | key是否有序不关心,需要更高的时间性能 |
4.3 迭代器遍历Set
Iterator< E> iterator() 返回迭代器,可以利用其进行遍历
Set<Integer> set = new TreeSet<>();set.add(1);set.add(3);set.add(2);set.add(8);set.add(4);Iterator<Integer> iterator = set.iterator();while (iterator.hasNext()) {System.out.print(iterator.next() + " ");}
运行结果:

5. 哈希表
5.1 哈希函数
- 哈希表的效率非常高,查找、删除、插入的时间复杂度都是O(1)。
- 理想的搜索方法:不经过任何比较,一次直接从表中得到想要搜索的元素,即一一映射关系。
- 哈希方法中使用的转换函数称为哈希函数,构造出来的结构称为哈希表(Hash Table)。
- 哈希函数计算出来的地址能均匀分布在整个空间中。
5.2 冲突
- 冲突: 不同关键字通过相同哈希函数计算出相同的哈希地址
- 冲突的发生是必然的,冲突是不可避免的,只能降低冲突率。
- 避免冲突:负载因子调节,其值= 填入表中的元素个数/哈希表的长度,因此可以增加哈希表的长度避免冲突。Java的系统库限制了荷载因子为0.75。
5.3 冲突的解决:开放地址法和链地址法
- 开放地址法(闭散列)
①线性探测
②二次探测
闭散列最大的缺陷:空间利用率比较低 - 链地址法(开散列) 数组+链表+红黑树
思路:首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于桶一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。
注意:数组长度>=64,链表长度>=8,就会变成红黑树。
5.4 哈希表与Java集合类的关系
- HashMap和HashSet是用哈希表实现的Map和Set。
- Java会在冲突链表长度大于一定阈值后,将链表转变成红黑树(搜索树)。
- Java中计算哈希值实际上调用的是类的hashcode方法,进行key的相等性比较是调用key的equals方法。
- 所有自定义类的HashMap的key或者HashSet的值,必须重写hashcode和euqals方法,而且必须做到euqals相等的对象,hashcode一定也是一样的。
- 扩容之后要注意每个元素都要重新计算hashcode哈希值。
面试问题:
- 问:如果2个对象hashcode一样,equals一定一样吗?
答:不一定,hashcode一样只能证明我们要找的位置一样,位置一样的下面有很多值,无法确定2个对象的euqals。- 问:如果2个对象equals一样,hashcode一定一样吗?
答:一定,equals一样则hashcode一定一样。
6. HashMap源码分析
6.1 成员变量
- 默认容量:16,最大容量:2的30次方

- 默认的负载因子:0.75

- 树化的条件(数组+链表变成红黑树)
链表长度超过8,数组的容量大于等于64
- 解树的条件(红黑树退化为链表+数组)
链表的阈值为6的时候

- table数组的每一个元素是node类型的结点地址

6.2 构造方法
- 不带参数的构造方法
负载因子等于默认的负载因子0.75,没有给table数组进行初始化,意味着table数组没有分配内存,数组的大小是0。
(所以,为什么等会put元素可以put进去?----> 说明在第一次put的时候,会把数组进行初始化为默认容量16)

- 带2个参数的构造方法
一个是给定的容量参数,一个是给定的负载因子参数

如果给定的参数容量大于2的30次方,则容量为2的30次方;
如果给定的参数容量小于0或者给定的负载因子小于0那么就抛异常。
最后负载因子满足条件直接赋值,但是容量还需要经过tableSizeFor进一步筛选。

tableSizeFor里面:返回最接近目标的一个二次幂整数。
例如:
传入10:2的3次方=8,2的4次方16,因此返回16。
面试题:调用构造方法给了1000,请问最后哈希数组的长度是多少?
答:1024

HashMap的最大容量保证是2的n次方,但是如果没有传入一个2的次方怎么办?
答:HashMap会将传入的参数做校验,返回距离传参最近的一个2的n次方的值,例如传入15会初始化为16。
那么,为什么返回二次幂呢?
分析put源码。
6.3 put方法源码

①先把key给到hash函数中,hash(key),调用hash方法,将引用类型key转换成整数类型

②hash这个方法中调用了hashcode方法,如果key重写了hashcode方法则会调用自己的hashcode方法,如果没有重写,则会调用Object类的hashcode方法。
h是通过hashcode方法得到的32位的整数,h 异或上 h右移16位
为什么要右移16位?
答:为了更好的均匀分布,低16位和高16位异或,可以让结果更均匀。
③i = (n - 1) & hash 等价于 n % len,位运算一定是最快的,一定要保证n是2的次幂,这样2个公式才等价。【所以初始化的长度为2的整数次幂】

相关文章:
Java Map和Set
目录1. 二叉排序树(二叉搜索树)1.1 二叉搜索树的查找1.2 二叉搜索树的插入1.3 二叉搜索树的删除(7种情况)1.4 二叉搜索树和TreeMap、TreeSet的关系2. Map和Set的区别与联系2.1 从接口框架的角度分析2.2 从存储的模型角度分析【2种模型】3. 关于Map3.1 Ma…...
【C/C++ 数据结构】-八大排序之 冒泡排序快速排序
作者:学Java的冬瓜 博客主页:☀冬瓜的主页🌙 专栏:【C/C数据结构与算法】 分享:那我便像你一样,永远躲在水面之下,面具之后! ——《画江湖之不良人》 主要内容:八大排序选…...
苹果ipa软件下载网站和软件的汇总
随着时间的流逝,做苹果版软件安装包下载网站和软件的渐渐多了起来。 当然,已经关站、停运、下架、倒闭的苹果软件下载网站和软件我就不说了,也不必多说那些关站停运下架倒闭的网站和软件了。 下面我统计介绍的就是苹果软件安装包下载网站和软…...
深度学习-【语义分割】学习笔记4 膨胀卷积(Dilated convolution)
文章目录膨胀卷积为什么需要膨胀卷积gridding effect连续使用三次膨胀卷积——1连续使用三次膨胀卷积——2连续使用三次膨胀卷积——3Understanding Convolution for Semantic Segmentation膨胀卷积 膨胀卷积,又叫空洞卷积。 左边是普通卷积,右边是膨胀…...
【10】SCI易中期刊推荐——工程技术-计算机:人工智能(中科院2区)
🚀🚀🚀NEW!!!SCI易中期刊推荐栏目来啦 ~ 📚🍀 SCI即《科学引文索引》(Science Citation Index, SCI),是1961年由美国科学信息研究所(Institute for Scientific Information, ISI)创办的文献检索工具,创始人是美国著名情报专家尤金加菲尔德(Eugene Garfield…...
模电计算反馈系数,有时候转化为计算电阻分压的问题
模电计算反馈系数,有时候转化为计算电阻分压的问题 如果是电压反馈,F的除数是Uo 如果是电流反馈,F的除数是Io 串联反馈,F的分子是Uf 并联反馈,F的分子是If 点个赞呗,大家一起加油学习!...
专治Java底子差,不要再认为泛型就是一对尖括号了
文章目录一、泛型1.1 泛型概述1.2 集合泛型的使用1.2.1 未使用泛型1.2.2 使用泛型1.3 泛型类1.3.1 泛型类的使用1.2.2 泛型类的继承1.4 泛型方法1.5 泛型通配符1.5.1 通配符的使用1)参数列表带有泛型2)泛型通配符1.5.2 泛型上下边界1.6 泛型的擦除1.6.1 …...
PayPal轮询收款的那些事儿
想必做跨境电商独立站的小伙伴,对于PayPal是再熟悉不过了,PayPal是一个跨国际贸易的支付平台,对于做独立站的朋友来说跨境收款绝大部分都是依赖PayPal以及Stripe条纹了。简单来说PayPal跟国内的支付宝有点类似,但是PayPal它是跨国…...
【Linux】项目自动化构建工具——make/Makefile
目录 1.make与Makefile的关系 Makefile make 项目清理 clean .PHONY 当我们编写一个较大的软件项目时,通常需要将多个源文件编译成可执行程序或库文件。为了简化这个过程,我们可以使用 make 工具和 Makefile 文件。Makefile 文件可以帮助我们自动…...
成本降低90%,OpenAI正式开放ChαtGΡΤ
今天凌晨,OpenAI官方发布ChαtGΡΤ和Whisper的接囗,开发人员现在可以通过API使用最新的文本生成和语音转文本功能。OpenAI称:通过一系列系统级优化,自去年12月以来,ChαtGΡΤ的成本降低了90%;现在OpenAI用…...
hls.js如何播放m3u8文件(实例)?
HLS(HTTP Live Streaming)是一种视频流传输协议,是苹果推出的适用于iOS与macOS平台的流媒体传输协议。它将视频分割成若干个小段,每个小段大小一般为2~10秒不等,并通过HTTP协议进行传输。通过在每个小段之间插入若干秒…...
大数据平台建设方法论集合
文章目录从0到1建设大数据解决方案大数据集群的方法论数据集成方法论机器学习算法平台方法论BI建设的方法论云原生大数据的方法论低代码数据中台的方法论大数据SRE运维方法论批流一体化建设的方法论数据治理的方法论湖仓一体化建设的方法论数据分析挖掘方法论数字化转型方法论数…...
25- 卷积神经网络(CNN)原理 (TensorFlow系列) (深度学习)
知识要点 卷积神经网络的几个主要结构: 卷积层(Convolutions): Valid :不填充,也就是最终大小为卷积后的大小. Same:输出大小与原图大小一致,那么N 变成了N2P. padding-零填充. 池化层(Subsampli…...
把数组里面数值排成最小的数
问题描述:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个。例如输入数组{12, 567},则输出这两个能排成的最小数字12567。请给出解决问题的算法,并证明该算法。 思路:先将…...
云his系统源码 SaaS应用 基于Angular+Nginx+Java+Spring开发
云his系统源码 SaaS应用 功能易扩 统一对外接口管理 一、系统概述: 本套云HIS系统采用主流成熟技术开发,软件结构简洁、代码规范易阅读,SaaS应用,全浏览器访问前后端分离,多服务协同,服务可拆分ÿ…...
小红书场景营销怎么做?场景营销主要模式有哪些
小红书作为新兴媒体领域的佼佼者,凭借着生动,直观,代入感等元素的分享推荐收揽了巨额的流量。但是,随着时代的脚步逐渐加快,发展和变革随之涌来,传统的营销已经无法满足。所以场景营销就出现了。今天就来和…...
c++基础——数组
数组数组是存放相同类型对象的容器,数组中存放的对象没有名字,而是要通过其所在的位置访问。数组的大小是固定的,不能随意改变数组的长度。定义数组数组的声明形如 a[b],其中,a 是数组的名字,b 是数组中元素…...
odoo15 登录界面的标题自定义
odoo15 登录界面的标题自定义 原代码中查询:<title>Odoo<title> <html> <head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Odoo</title><link rel="shortcut icon…...
【内网服务通过跳板机和公网通信】花生壳内网穿透+Nginx内网转发+mqtt服务搭建
问题:服务不能暴露公网 客户的主机不能连外网,服务MQTT服务部署在内网。记做:p1 (computer 1)堡垒机(跳板机)可以连外网,内网IP 和 MQTT服务在同一个网段。记做:p2 (computer 2)对他人而言&…...
【多线程常见面试题】
谈谈 volatile关键字的用法? volatile能够保证内存可见性,强制从主内存中读取数据,此时如果有其他线程修改被volatile修饰的变量,可以第一时间读取到最新的值 Java多线程是如何实现数据共享的? JVM把内存分成了这几个区域: 方法区,堆区,栈区,程序计数器; 其中堆区…...
小米Pad 5 Windows驱动完整配置指南:解锁平板的桌面级生产力
小米Pad 5 Windows驱动完整配置指南:解锁平板的桌面级生产力 【免费下载链接】MiPad5-Drivers Based on Surface Duo Drivers. 项目地址: https://gitcode.com/gh_mirrors/mi/MiPad5-Drivers 想要让小米Pad 5变身真正的生产力工具吗?这款基于高通…...
从零开始:使用TCP调试助手V1.9进行网络通信调试的完整流程
从零开始:使用TCP调试助手V1.9进行网络通信调试的完整流程 在软件开发与网络调试领域,TCP/UDP通信测试是每个开发者迟早要面对的必修课。无论是物联网设备的数据传输验证,还是分布式系统的组件间通信检查,一个可靠的调试工具能让我…...
快速上手ANIMATEDIFF PRO:从环境部署到视频导出的完整操作流程
快速上手ANIMATEDIFF PRO:从环境部署到视频导出的完整操作流程 1. 环境准备与快速部署 1.1 硬件要求检查 在开始之前,请确保您的设备满足以下最低配置要求: 显卡:NVIDIA RTX 3060及以上(推荐RTX 4090)显…...
Qwen3-0.6B-FP8企业级部署教程:基于Dify打造AI应用平台
Qwen3-0.6B-FP8企业级部署教程:基于Dify打造AI应用平台 想快速搭建一个属于自己或团队的AI应用,但又觉得从零开发太复杂?今天,我们就来聊聊如何用Qwen3-0.6B-FP8这个轻量高效的模型,结合Dify这个强大的AI应用开发平台…...
企业IT必看:教员工用小米手机配置Exchange邮箱的完整指南(含服务器参数详解)
企业IT标准化指南:小米手机Exchange邮箱配置与服务器参数解析 在移动办公成为标配的今天,企业邮箱的稳定接入直接关系到团队协作效率。根据2023年企业通信工具调研报告,超过67%的中大型企业仍在使用Exchange作为核心邮件系统,而员…...
5种场景轻松搞定抖音视频保存 开源工具让无水印下载变简单
5种场景轻松搞定抖音视频保存 开源工具让无水印下载变简单 【免费下载链接】douyin_downloader 抖音短视频无水印下载 win编译版本下载:https://www.lanzous.com/i9za5od 项目地址: https://gitcode.com/gh_mirrors/dou/douyin_downloader 在数字内容爆炸的时…...
Ollama镜像免配置原理:daily_stock_analysis启动脚本中systemd服务注册与健康检查逻辑
Ollama镜像免配置原理:daily_stock_analysis启动脚本中systemd服务注册与健康检查逻辑 1. 项目背景与核心价值 在当今AI技术快速发展的时代,本地化部署大模型成为了许多企业和开发者的迫切需求。daily_stock_analysis镜像正是基于这一需求,…...
百度网盘提取码智能获取:3分钟解锁加密资源的秘密武器
百度网盘提取码智能获取:3分钟解锁加密资源的秘密武器 【免费下载链接】baidupankey 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 还在为百度网盘上那些需要提取码的资源而烦恼吗?每次遇到心仪的学习资料、软件工具或影视资源&…...
【Python工业视觉部署黄金法则】:20年实战总结的5大避坑指南与实时推理加速秘籍
第一章:Python工业视觉部署的工程化本质与挑战全景工业视觉系统在产线落地时,远非“模型训练完成 → 用OpenCV加载推理”这般线性。其核心矛盾在于:算法原型追求精度与泛化,而工程部署必须兼顾实时性、鲁棒性、可维护性与硬件约束…...
终极指南:Shenyu网关集成Polaris服务治理平台的完整教程
终极指南:Shenyu网关集成Polaris服务治理平台的完整教程 Shenyu网关作为基于Spring Cloud的高性能API网关,与Polaris服务治理平台的集成能够为企业级微服务架构提供强大的流量控制和动态配置能力。本教程将详细讲解如何从零开始配置Shenyu网关与Polaris…...

