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把内存分成了这几个区域: 方法区,堆区,栈区,程序计数器; 其中堆区…...
深度剖析指针(下)——“C”
各位CSDN的uu们你们好呀,今天小雅兰的内容还是我们的指针呀,上两篇博客我们基本上已经把知识点过了一遍,这篇博客就让小雅兰来带大家看一些和指针有关的题目吧,现在,就让我们进入指针的世界吧 复习: 数组和…...
爬虫与反爬虫技术简介
互联网的大数据时代的来临,网络爬虫也成了互联网中一个重要行业,它是一种自动获取网页数据信息的爬虫程序,是网站搜索引擎的重要组成部分。通过爬虫,可以获取自己想要的相关数据信息,让爬虫协助自己的工作,…...
Pag的2D渲染执行流程
Pag的渲染 背景 根据Pag文章里面说的,Pag之前长时间使用的Skia库作为底层渲染引擎。但由于Skia库体积过大,为了保证通用型(比如兼容CPU渲染)做了很多额外的事情。所以Pag的工程师们自己实现了一套2D图形框架替换掉Skiaÿ…...
k8s 概念说明,k8s面试题
什么是Kubernetes? Kubernetes是一种开源容器编排系统,可自动化应用程序的部署、扩展和管理。 Kubernetes 中的 Master 组件有哪些? Kubernetes 中的 Master 组件包括 API Server、etcd、Scheduler 和 Controller Manager。 Kubernetes 中的…...
Docker--(四)--搭建私有仓库(registry、harbor)
私有仓库----registry官方提供registry仓库管理(推送、删除、下载)私有仓库----harbor私有镜像仓库1.私有仓库----registry官方提供 Docker hub官方已提供容器镜像registry,用于搭建私有仓库 1.1 镜像拉取、运行、查看信息、测试 (一) 拉取镜像 # dock…...
Invalid <url-pattern> [sso.action] in filter mapping
Tomcat 8.5.86版本启动web项目报错Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> [sso.action] in filter mapping 查看项目的web.xml文件相关片段 <filter-mapping><filter-name>SSOFilter</filter-name><url-pattern&g…...
【11】linux命令每日分享——useradd添加用户
大家好,这里是sdust-vrlab,Linux是一种免费使用和自由传播的类UNIX操作系统,Linux的基本思想有两点:一切都是文件;每个文件都有确定的用途;linux涉及到IT行业的方方面面,在我们日常的学习中&…...
Newman+Jenkins实现接口自动化测试
一、是什么Newman Newman就是纽曼手机这个经典牌子,哈哈,开玩笑啦。。。别当真,简单地说Newman就是命令行版的Postman,查看官网地址。 Newman可以使用Postman导出的collection文件直接在命令行运行,把Postman界面化运…...
MySQL:事务+@Transactional注解
事务 本章从了解为什么需要事务到讲述事务的四大特性和概念,最后讲述MySQL中的事务使用语法以及一些需要注意的性质。 再额外讲述一点Springboot中Transactional注解的使用。 1.为什么需要事务? 我们以用户转账为例,假设用户A和用户B的银行账…...
数字IC手撕代码--低功耗设计 Clock Gating
背景介绍芯片功耗组成中,有高达 40%甚至更多是由时钟树消耗掉的。这个结果的原因也很直观,因 为这些时钟树在系统中具有最高的切换频率,而且有很多时钟 buffer,而且为了最小化时钟 延时,它们通常具有很高的驱动强度。 …...
版式网站有哪些/如何在百度上做免费推广
onTouch与onClick之间会产生事件冲突吗? 事件在控件中时如何传递的? 事件冲突的根本原因? 如何解决事件冲突? View的事件分发机制 View的事件分发机制就是事件的传递过程,也就是一个Down事件,若干个Move事…...
汉沽网站建设制作/市场营销培训
目录 一:介绍 二:计时器Timer类的编写 三:计时器管理TimerManager类的编写 四:使用方法 一:介绍 这里我们使用List来管理定义的所有计时器Timer,首先就是需要构建计时器的完整逻辑,包括计时…...
怎么样免费做网站/平台运营
原标题:LOL最强的钩子是谁的?不是机器人,也不是锤石,而是他!在LOL中,最具功能性的技能,应该就是那些钩人的技能了。这些有钩子技能的英雄,不管是开团,还是保人࿰…...
网站建设中文百/网站排名优化公司哪家好
又有一段时间没有进行整理和总结输出了,其实最近也没有闲着,也是一直在看书学习状态,看Java并发编程相关的知识,之前买了《Java并发编程的艺术》,去年看了一遍。最近又买了《Java并发编程实战》,两本书都挺…...
网站建设服务合同是否缴纳印花税/四川旅游seo整站优化站优化
Java 基础语法 一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。下面简要介绍下类、对象、方法和实例变量的概念。 对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,…...
WordPress无法显示摘要/优化设计单元测试卷
import matplotlib.pyplot as plt import numpy as npx np.arange(20) y x**2plt.plot(x, y) 在jupyter notebook中使用matplotlib画图出现这个错误,修正方法: sudo pip install matplotlib2.2.0...