--- java数据结构 map set ---

news2024/11/22 6:03:52

java中map 和 set的底层实现是通过搜索树和哈希函桶来实现 

搜索树

二叉搜索树有叫二叉排序树 他具有以下的特点

若存在左节点,那么他左节点的值一定小于根节点

若存在右节点,那么他右节点的值一定大于根节点

它的左右子树也是搜索树

对他进行中序遍历会的到一个升序的数组,且能达到去重的效果

二叉搜索树的实现

字段的实现

二叉树的插入

先找到要插入的位置,在插入时和节点的值比较,若小于该节点的值就往做边走,大于就往右边走

,这样一直走到null,那么这个位置就是我们要插入的位置,但是我们没有这个位置的父节点,所以需要一个parent来记录父节点

非递归

递归

查找

其实在实现插入的时后也就随便实现了查找,在给二叉树找到合适的插入位置时,当该值和节点值相同时就返回true 若没有那就返回false

删除

找到要删除的值对于的节点

删除比较麻烦 要分3中情况考虑

 

1,若删除的节点的左节点为空 ,那么直接删除该节点就好 

2,若右节点为空,那么也是直接删除节点就好

3,如果左右都不为空 那么就不呢直接删除节点了,因为左右还要节点,这要使用左边节点替代?还是右边?且左右节点都可能右节点的,显然不行

那么我们可以使用替换删除,使用15左树最大的值或者右树最小的值去取代15

搜索树是否创建成功,可以使用中序遍历来检查,正确的搜索树中序遍历会的到一个升序的数组

map set 是一种专门用来进行搜索的数据结构,搜索的效率和他实例化子类(Tree  hash)有关

模型

一般吧查找数据的关键字称为key 而与key对应的值就是value

K-V模型 比如查找单词 和对应单词的出现次数 <单词,出现的次数> 对于的数据结构时Map

纯K模型 只有Key 对于的数据结构是Set

map的使用

put(key,value)

插入数据在map中 key独一无二的

get(key)根据key返回对应的value
containsKey(key)

判断key是否存在于map中

返回值时boolean类型

containsValue(value)

判断value是否存在于map中

返回值时boolean类型

getOrDefault(key,default)

获得key对应的value,如果

不存在那么就返回default的值

isEmpty()map是不是为空
clear()清空map
remove(key)

删除对应key-value键值,并

返回key对应的value

remove(key,value)

删除对应的key-value键值

返回值时boolean类型

size()返回键值对个数
replace(key,value)

将key对应的value修改为传

入的value值,并返回的是key

未修改前的值

repalce(key,oldValue,newValue)

将key对应的oldValue修改为

newValue对应的值,返回值是

boolean类型,若k-v不匹配,那么

替换会失败

toString()

返回一个字符串,包括map所有

k-v数据

keySet()将map中的所有key以set返回
values()

放回value的可重复集,返回类型为

Collection<V> 

set的使用

add(key)插入key到set中
contains(key)

判断set中是否存在key

返回值是boolean类型

remove(key)删除key
size()返回set大小
clear()

清空set

toArray()将set中的所有key以数组形式返回
toArray(T[] a)             

将set中的所有key以数组形式返回

传入的a是是key类型的数组

返回的也是key类型的数组

isEmpty()set是否为空
iterator()返回一个迭代器 可用来遍历set
containsAll(Collection<?> c)

c集合中的值是否在set都存在,

若是那么就返回true 否false

removeAll(Collection<?> c)删除set中含有的集合c中的值
addAll(Collection<? extends E> c)将c中的所有值加到set中,会去重

map和set

map的底层结构

TreeMapHashMap
底层结构红黑树(也是搜索树)哈希桶

插入,删除,查找

时间复杂度

O(logN)O(1)
是否有序关于k有序无序
删除 插入 查找区别需要进行元素之间的比较通过哈希函数直接进行查找
适用范围需要key有序的情况下不在乎有无序,需要更高的效率

set的底层结构

TreeSetHashSet
底层结构红黑树哈希桶

插入,删除,查找

时间复杂度

O(logN)O(1)
是否有序关于k有序无序
删除 插入 查找区别需要进行元素之间的比较通过哈希函数直接进行查找
适用范围需要key有序的情况下不在乎有无序,需要更高的效率

哈希表

在顺序结构和树结构中进行数据的查询时,因为没有与查找的数据对应的关键码,所以在查找数据时会进行多次的数据之间的比较,而就是这些比较会大大增加我们的查找时间,所以时间复杂度会到达logN 或n^2这么高

而理想的查找查找方式是不同过任何比较,一次就找到这个数据,那么如果构造一种数据结构,他可以将数据和数据的关键码进行一一映射的关系,通过这个关键码就可以联系到该数据的位置,那么他的时间复杂度就可以达到O(1)

向该数据结构中插入数据

通过插入该函数的关键码来计算出该数据的储存位置,并吧该数据储存在该位置

查找数据

也是通过关键码计算出该数据的储存位置,在该位置找到对饮的数据

这种方法便是哈希(散列)方法,据此对应的数据结构就是哈希表(散列表),将关键码转换为特殊的数值的函数便是哈希函数

粗略的哈希表的表示  

这样如果要找8这个数据,我们可以通过哈希函数计算出他对饮的下标便是0 然后直接arr[0]就得到了8 这样没有通过比较,一次变就找到了需要的数据

哈希冲突

对于俩个数据的关键字在哈希函数中计算出哈希地址可能会出现相同的值的情况,比如1 % 7 = 1    8 % 7 = 1 这种情况就叫做哈希冲突 或者是哈希碰撞,若有不同的数据通过哈希函数计算出相同的哈希地址那么就称这写数据叫做 "同义词"

避免

在哈希底层的空间大小是小于实际储存数据所需要的大小,因为要达到O(1)的访问速度,那么就需要用到数组,通过下标直接访问该位置,算出的哈希地址会是充满随机性的,数组的大小不够是经常的事,那么发生冲突就是难以避免的,而我们能做的也就是降低冲突率

减低冲突率的方法

哈希函数的设计

设计的哈希函数的定义域应该包含需要储存的所有关键码,如果散列表有m个地址,那么设计的哈希函数的定义域就该在0 ~ m-1之间

哈希函数计算出的哈希地址应该平均分布在定义域之间

哈希函数要足够简单

当然设计哈希函数是很困难的是,直接用java中给的就好

哈希函数设计的越好,他的冲突率就越低,但是不能避免哈希冲突的发生

负载因子调节

散列表的负载因子定义 a = 有效元素的个数 / 总的储存空间的大小

 因为表长的定值,所以a和储存和储存的元素个数的数量成正比,而储存的元素数量越多,那么他的发生哈希冲突的概率越高,在开发地址中冲突率应该在0.7~0.8之间,超过这个区间,那么在查找过程中发生哈希冲突的概率按曲线上升,会大大减低哈希表的查询效率

要降低负载因子的大小,要么减少储存的元素个数,当然这时不行的,那么就只有增大储存空间的大小

冲突解决

解决哈希冲突的俩总常用方式,开散列和闭散列

闭散列

闭散列 也叫开放定址法,当发生哈希冲突时,若哈希表为装满,那么说明还有空位置,那么就把这个数据放到这个空位中去,那么这个空位要怎么寻找呢

线性探测

将数据从发生哈希冲突的这个位置开始,向后寻找,找到空的为位置,那么就把这个值放到这里

.

对于闭散列,在删除时不能直接吧该数据直接改变,会影响之后数据的查询,比如如果删除了2这个数据,那么在之后查找22这个数据时,会发现计算到的哈希地址为2,为2这个位置为空,那么查询就出了错误

二次探测

线性探测的缺点是会产生冲突数据的冗余,因为该数据是直接向后找到空位然后储存

为了降低线性探测的冲突数据冗余的情况,适二次探测来将冗余数据分散开来储存

那么二次探测寻找空位置的方式就是:add = (x + i^2)% m,x是计算出的哈希地址,i是1,2,3……m是数组的大小

对与闭散列最大的缺点就是空间利用率低,这也是哈希的缺陷

开散列 --哈希桶(更合理的冲突解决方法)

开散列又叫开地址法(开链法),数组中储存的是一个链表,将发生冲突的元素储存在一个链表中

这样查找时秩序要遍历这个链表就能找到数据

当表中的a达到的负载因子,那么就要对数组进行resize,扩容数组时需要遍历整个哈希表,然后吧数据放到对应的位置上

若随着数据的插入越来越多,链表上的数据多与一定的数目之后(64),那么这时的查询效率会大大减低,所以这时又会将该链表转换为红黑树(高度比较平衡的搜索树),用来增加查询的效率

开散列的实现

字段设计

add

先计算储存的有效元素个数是否小于负载因子,若不是那么就要扩容了,是的话那么直接吧该值放到对应的下标中,放的时候要对下标进行判断,若这个下标已经有数据存在,那么就见该值插入这个数据后,

poll

通过哈希函数计算除该数据对应的下标,然后判断该下标是否存在数据,若有,那么遍历这个链表来找到对应数值并删除

是否存在该数据

和删除时查找删除数据一样的

判断是否需要扩容

但达到的负载因子大小后 扩容

遍历整个哈希桶,并将每个数据放到新扩容的桶中去

哈希桶实现其实是哈希函数+数组+链表实现的,不过既然已经存在了链表,那么为什么查找效率还是O(1)呢

那是因为即使有了链表,但我们仍然可以认为链表长度时个常数,查找所需的实际可以忽略

在java中进行哈希值的计算实际上调用的时HashCode这个类,而对key的比较是调用的是equals这个方法,所以如果要将自定义类储存在HashMap或者HashSet中的话,那么需要重写equals和HashCode这俩个方法

在java类的继承中Map是没有继承与collection接口,而Set是继承了collection接口

EDN~~

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

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

相关文章

leetcode热题100.最长公共子序列

题目 1143. 最长公共子序列 - 力扣&#xff08;LeetCode&#xff09; 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原…

SOMEIP_ETS_143: SD_Request_non_existing_ServiceID

测试目的&#xff1a; 验证DUT能够拒绝一个请求不存在的服务ID&#xff08;ServiceID&#xff09;的SubscribeEventgroup消息&#xff0c;并以SubscribeEventgroupNAck作为响应。 描述 本测试用例旨在确保DUT遵循SOME/IP协议&#xff0c;当接收到一个请求不存在服务ID的Subs…

RS485串口通信:【图文详讲】

RS485&#xff0c;RS的意义为Recommended Standard的缩写&#xff0c;也就是推荐标准&#xff0c;是一种常用的半双工-异步-串行通信总线。半双工的意思就是两者通信时&#xff0c;同一时刻&#xff0c;只能由其中一方发送&#xff0c;另一方只能接收&#xff0c;不可以同时收发…

vue3 antdv3/4 Modal显示一个提示,内容换行显示。

1、官网地址&#xff1a; Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.js 2、显示个信息&#xff1a; Modal.info({title: This is a notification message,content: h(div, {}, [h(p, some messages...some messages...),h(p, some …

基于解压缩模块的JPEG同步重压缩检测论文学习

一、论文基本信息&#xff1a; 论文题目&#xff1a;基于解压缩模块的JPEG同步重压缩检测 作者&#xff1a;王金伟1 &#xff0c;胡冰涛1 &#xff0c;张家伟1 &#xff0c;马 宾2 &#xff0c;罗向阳3 &#xff08;1.南京信息工程大学计算机学院、网络空间安全学院&#xf…

Linux-L11-查看本机ip地址

linux查看ip地址 查看自己的IP地址使用 ip 命令&#xff1a;使用 ifconfig 命令使用 hostname 命令&#xff1a;使用 nmcli 命令 查看某个特定接口的IP查看公网IP地址 在Linux系统中&#xff0c;查看自己的IP地址可以通过多种方式实现&#xff0c;这里提供几种常用的方法&#…

Stable Diffusion绘画 | LCM模型:实现秒出图

在过往&#xff0c;不管使用 SD 还是 MJ&#xff0c;生成一张图片起码要等上10秒。 而现在&#xff0c;有了 LCM 技术的加持&#xff0c;已经能做到秒出图&#xff0c;甚至是实时出图。 LCM(潜空间一致性模型) 是由 清华大学信息科学技术研究院 研发的大模型&#xff0c;它最…

鸿蒙 如何退出 APP

terminateSelf() 停止Ability自身 在EntryAbility中这么使用 this.context.terminateSelf()在Pages页面中这么使用 import { common } from kit.AbilityKit (getContext(this) as common.UIAbilityContext)?.terminateSelf() 也可以直接封装&#xff1a; import common f…

【GreenHills】GHS的Run-Time检查功能

【更多软件使用问题请点击亿道电子官方网站】 一、文档背景 在编写代码时&#xff0c;内存检查的重要性不容忽视。内存是程序运行的核心资源之一&#xff0c;负责存储程序运行所需的数据。由于内存资源的有限性和操作的复杂性&#xff0c;内存错误常常会直接导致程序崩溃、性…

华为开源自研AI框架昇思MindSpore应用案例:基于MindSpore框架的Swin Transformer

如果你对MindSpore感兴趣&#xff0c;可以关注昇思MindSpore社区 模型简介 模型背景 Swin Transfromer在2021年首次发表于论文《Swin Transformer: Hierarchical Vision Transformer using Shifted Windows》&#xff0c;目前已用于图像分割、分类等计算机视觉领域的各项任务…

如何搭建医疗陪诊平台?基于互联网医院系统源码的开发技术详解

本篇文章&#xff0c;小编将深入探讨医疗陪诊平台的搭建过程&#xff0c;尤其是基于互联网医院系统源码的开发技术&#xff0c;以期为有志于此领域的开发者提供参考。 一、选择合适的互联网医院系统源码 在搭建医疗陪诊平台时&#xff0c;选择合适的互联网医院系统源码至关重…

【前端开发入门】前端开发环境配置

目录 引言一、Vscode编辑器安装1. 软件下载2. 软件安装3. 插件安装 二、Nodejs环境安装及版本控制1. 安装内容2. 使用nvm安装2.1 软件下载并安装2.2 nvm基本指令2.3 nvm下载过慢导致超时解决 三、git安装及配置1. 软件下载2. 软件安装3. 基础配置 四、总结 引言 本系列教程旨在…

SRC漏洞挖掘 | 针对Spring-Boot 框架漏洞的初探

&#x1f497;想加内部圈子&#xff0c;请联系我&#xff01; &#x1f497;文章交流&#xff0c;请联系我&#xff01;&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 一个想当文人的黑客 &#xff0c;很高兴认识大家~ ✨主…

fmt:C++ 格式化库

fmt 是一个现代化、快速且安全的 C 格式化库&#xff0c;专注于高效地格式化文本。它提供了类似 Python 的 format 功能&#xff0c;但具有更高的性能和类型安全特性。fmt 库在处理字符串格式化、日志输出以及构建用户友好的输出时尤为强大。自从 C20 标准引入 std::format 后&…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《故障扰动下的风火储送端系统频率动态特性与储能容量优化配置》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

婚前协议模版(琴生生物机械科技工业研究所)

婚前协议示例 本协议由甲方&#xff08;全名&#xff09;&#xff0c;身份证号码&#xff08; _________ &#xff09;&#xff0c;与乙方&#xff08;全名&#xff09;&#xff0c;身份证号码&#xff08; _________ &#xff09;&#xff0c;在平等、自愿、相互尊重及充分沟…

DataEase v2 开源代码 Windows 从0到1环境搭建

一、环境准备 功能名称 描述 其它 操作系统 Windows 数据库 Mysql8.0 开发环境 JDK17以上 本项基于的21版本开发 Maven 3.9版本 开发工具 idea2024.2版本 前端 VSCode TIPS&#xff1a;如果你本地有jdk8版本&#xff0c;需要切换21版本&#xff0c;请看…

[python] 基于PyOD库实现数据异常检测

PyOD是一个全面且易于使用的Python库&#xff0c;专门用于检测多变量数据中的异常点或离群点。异常点是指那些与大多数数据点显著不同的数据&#xff0c;它们可能表示错误、噪声或潜在的有趣现象。无论是处理小规模项目还是大型数据集&#xff0c;PyOD提供了50多种算法以满足用…

解决银河麒麟fcitx进程资源占用高的问题

解决银河麒麟fcitx进程资源占用高的问题 1、问题描述2、解决方法 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 1、问题描述 银河麒麟桌面系统中&#xff0c;fcitx进程占用CPU和内存过高&#xff0c;导致系统卡顿。 2、解决方法 卸载并清…

OPENCV判断图像中目标物位置及多目标物聚类

文章目录 在最近的项目中&#xff0c;又碰到一个有意思的问题需要通过图像算法来解决。就是显微拍摄的到的医疗图像中&#xff0c;有时候目标物比较偏&#xff0c;也就是在图像的比较偏的位置&#xff0c;需要通过移动样本&#xff0c;将目标物置于视野正中央&#xff0c;然后再…