模拟解决哈希表冲突
目录
解决哈希表冲突原理:
模拟解决哈希表冲突代码:
负载因子:
动态扩容:
总结:
HashMap和HashSet的总结:
解决哈希表冲突原理:
黑色代表一个数组,当 出现哈希冲突时(相同数组下标),该位置下标会变成一个链表(上图红色区域)。这样就能存储了。叫做开散列 / 哈希桶。链表长度超过阈值(默认8)时转为红黑树,优化冲突性能。
虽然哈希表⼀直在和冲突做斗争,但在实际使用过程中,我们认为哈希表的冲突率是不高的,冲突个数是可控的,也就是每个桶中的链表的长度是⼀个常数,所以,通常意义下,我们认为哈希表的插⼊/ 删除/查找时间复杂度是O(1)。
模拟解决哈希表冲突代码:
private static class Node {private int key;private int value;Node next;public Node(int key, int value) {this.key = key;this.value = value;}}private Node[] array;private int size; // 当前的数据个数private static final double LOAD_FACTOR = 0.75; //默认最大负载因子private static final int DEFAULT_SIZE = 8; //默认桶的大小//初始化哈希桶public HashBucket() {array = new Node[DEFAULT_SIZE];}//放元素public int put(int key, int value) {//1.遍历index数组下的链表,如果有相同的key则更新valint index = key % array.length;Node cur = array[index];while(cur != null) {if(cur.key == key) {cur.value = value;return 1;}cur = cur.next;}//2.头插法擦插入节点Node node = new Node(key,value);node.next = array[index];array[index] = node;//3.重新计算当前的负载因子 是不是超过了 我们规定的负载因子if(loadFactor() >= LOAD_FACTOR) {//扩容resize();}return -1;}//扩容private void resize() {// write code hereNode[] newArray = new Node[array.length * 2];for (int i = 0; i < array.length; i++) {Node cur = array[i];while(cur != null) {int newindex = cur.key % newArray.length;//把当前节点 放到新的数组的 newindex 位置 头插法Node curN = cur.next;cur.next = newArray[newindex];newArray[newindex] = cur;cur = curN;}}array = newArray;}//计算负载因子private double loadFactor() {return size * 1.0 / array.length;}//取对应key的value值public int get(int key) {// write code hereint index = key % array.length;Node cur = array[index];while (cur != null) {if(cur.key == key) {return cur.value;}cur = cur.next;}return -1;}
负载因子:
哈希表中已存储的元素数量(n
)与哈希表的容量(m
)的比值,通常用公式表示为:
负载因子 = 已存储元素数量哈希表容量 / 哈希表容量。
例如,一个哈希表的容量是 100,当前已经存储了 50 个元素,那么此时该哈希表的负载因子就是 50 / 100 = 0.5
负载因子主要用于衡量哈希表的空间使用程度和性能,它直接影响哈希表的插入、查找和删除操作的效率:
空间利用率:负载因子越大,说明哈希表中存储的元素越满,空间利用率越高;反之,负载因子越小,空间利用率越低,意味着有较多的空闲存储桶。
冲突概率:冲突是指不同的键通过哈希函数计算得到了相同的存储桶索引。负载因子越大,发生冲突的概率就越高。因为随着元素数量的增加,有限的存储桶被占用的比例也在增大,新元素更容易被映射到已经有元素的桶中。
动态扩容:
为了保证哈希表在不同的元素数量下都能保持较好的性能,当负载因子超过某个阈值(通常是默认的负载因子)时,哈希表会进行动态扩容操作。具体步骤如下:
- 创建更大的哈希表:通常新的哈希表容量是原容量的 2 倍。
- 重新哈希:将原哈希表中的所有元素重新计算哈希值,并插入到新的哈希表中。
- 更新引用:将原哈希表的引用指向新的哈希表。
总结:
1.java 中使用的是哈希桶方式解决冲突的。
2.java 会在冲突链表长度大于一定阈值后,将链表转变为搜索树(红黑树)。
3. java 中计算哈希值(相当于计算出的数据应该在数组放的下标位置)实际上是调用的类的 hashCode 方法,进行 key 的相等性比较是调用 key 的 equals 方法。
所以如果要用自定义类作为 HashMap 的 key 或者 HashSet 的值,必须重写 hashCode 和 equals 方法,而且要做到 equals 相等的对象,hashCode ⼀定是⼀致的:
比如:
import java.util.HashMap;
import java.util.Map;class Person {private int id;public Person(int id) {this.id = id;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return id == person.id;}@Overridepublic int hashCode() {return id;}
}public class HashMapDuplicateKeyExample {public static void main(String[] args) {Map<Person, String> map = new HashMap<>();Person p1 = new Person(1);Person p2 = new Person(1);map.put(p1, "Alice");map.put(p2, "Bob");System.out.println(map.size()); // 输出: 1}
}
代码过程:
HashMap
先计算 p1
的哈希码,因为 p1
的 id
是 1
,所以哈希码就是 1
根据这个哈希码找到对应的哈希桶,把键值对 (p1, "Alice")
存进去。
HashMap
计算 p2
的哈希码,由于 p2
的 id
也是 1
,所以哈希码同样是 1
,和 p1
的哈希码一样,会对应到同一个哈希桶。
接着,HashMap
会用 equals()
方法比较 p1
和 p2
,因为 p1
和 p2
的 id
相等,equals()
方法返回 true
,这表明 p1
和 p2
是相同的键。
此时,HashMap
不会再新增一个键值对,而是用新的值 "Bob"
覆盖掉原来键 p1
(和 p2
视为相同键)对应的值 "Alice"
。
由于 p1
和 p2
被 HashMap
判定为相同的键,所以 HashMap
里实际上只有一个键值对,调用 map.size()
就会输出 1
。
此段代码我们知道:
hashCode
方法用于确定键对象在哈希表中的存储位置。
如果两个键的 hashCode
相同,并且 equals
方法返回 true
,则认为这两个键是相同的,后插入的键值对会覆盖之前的。
HashMap和HashSet的总结:
特性 | HashMap | HashSet | |
存储结构 | 键值对(Key-Value) | 单一对象(Key) | |
重复元素 | 键唯一,值(value)可重复 | 元素唯一 | |
null支持 | 1个null键,多个null值 | 1个null元素 | |
底层原理 | 哈希表(数组+链表 / 红黑树) | HashMap | |
核心方法 | put(), get(), remove() | add(), remove(), contains() | |
应用场景 | 键值映射、缓存 |
|
相关文章:
模拟解决哈希表冲突
目录 解决哈希表冲突原理: 模拟解决哈希表冲突代码: 负载因子: 动态扩容: 总结: HashMap和HashSet的总结: 解决哈希表冲突原理: 黑色代表一个数组,当 出现哈希冲突时࿰…...
UIView 与 CALayer 的联系和区别
今天说一下UIView 与 CALayer 一、UIView 和 CALayer 的关系 在 iOS 开发中,UIView 是用户界面的基础,它负责处理用户交互和绘制内容,而 CALayer 是 UIView 内部用于显示内容的核心图层(Layer)。每个 UIView 内部都有…...
Android 10.0 移除wifi功能及相关菜单
介绍 客户的机器没有wifi功能,所以需要删除wifi相关的菜单,主要有设置-网络和互联网-WLAN,长按桌面设置弹出的WALN快捷方式,长按桌面-微件-设置-WLAN。 修改 Android10 上直接将config_show_wifi_settings改为false,这样wifi菜单的入口就隐…...
电力与能源杂志电力与能源杂志社电力与能源编辑部2024年第6期目录
研究与探索 含电动汽车虚拟电厂的优化调度策略综述 黄灿;曹晓满;邬楠; 643-645663 含换电站的虚拟电厂优化调度策略综述 张杰;曹晓满;邬楠;杨小龙; 646-649667 考虑虚拟负荷研判的V2G储能充电桩设计研究 徐颖;张伟阳;陈豪; 650-654 基于状态估计的电能质量监测…...
简站主题:简洁、实用、SEO友好、安全性高和后期易于维护的wordpress主题
简站主题以其简洁的设计风格、实用的功能、优化的SEO性能和高安全性而受到广泛好评。 简洁:简站主题采用扁平化设计风格,界面简洁明了,提供多种布局和颜色方案,适合各种类型的网站,如个人博客和企业网站。 实用&…...
Redis(高阶篇)03章——缓存双写一致性之更新策略探讨
一、反馈回来的面试题 一图你只要用缓存,就可能会涉及到redis缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性的问题双写一致性,你先动缓存redis还是数据库mysql哪一个&#x…...
【Git】说说Git中开发测试的使用Git分支Git标签的使用场景
一、环境介绍 dev环境:开发环境,外部用户无法访问,开发人员使用,版本变动很大。test环境:测试环境,外部用户无法访问,专门给测试人员使用的,版本相对稳定。pre环境:灰度环…...
Spring Boot中使用Server-Sent Events (SSE) 实现实时数据推送教程
一、简介 Server-Sent Events (SSE) 是HTML5引入的一种轻量级的服务器向浏览器客户端单向推送实时数据的技术。在Spring Boot框架中,我们可以很容易地集成并利用SSE来实现实时通信。 二、依赖添加 在Spring Boot项目中,无需额外引入特定的依赖&#x…...
【Golang学习之旅】Go 语言微服务架构实践(gRPC、Kafka、Docker、K8s)
文章目录 1. 前言:为什么选择Go语言构建微服务架构1.1 微服务架构的兴趣与挑战1.2 为什么选择Go语言构建微服务架构 2. Go语言简介2.1 Go 语言的特点与应用2.2 Go 语言的生态系统 3. 微服务架构中的 gRPC 实践3.1 什么是 gRPC?3.2 gRPC 在 Go 语言中的实…...
数据结构:栈(Stack)及其实现
栈(Stack)是计算机科学中常用的一种数据结构,它遵循先进后出(Last In, First Out,LIFO)的原则。也就是说,栈中的元素只能从栈顶进行访问,最后放入栈中的元素最先被取出。栈在很多应用…...
DeepSeek在linux下的安装部署与应用测试
结合上一篇文章,本篇文章主要讲述在Redhat linux环境下如何部署和使用DeepSeek大模型,主要包括ollama的安装配置、大模型的加载和应用测试。关于Open WebUI在docker的安装部署,Open WebUI官网也提供了完整的docker部署说明,大家可…...
Next.js【详解】获取数据(访问接口)
Next.js 中分为 服务端组件 和 客户端组件,内置的获取数据各不相同 服务端组件 方式1 – 使用 fetch export default async function Page() {const data await fetch(https://api.vercel.app/blog)const posts await data.json()return (<ul>{posts.map((…...
pnpm, eslint, vue-router4, element-plus, pinia
利用 pnpm 创建 vue3 项目 pnpm 包管理器 - 创建项目 Eslint 配置代码风格(Eslint用于规范纠错,prettier用于美观) 在 设置 中配置保存时自动修复 提交前做代码检查 husky是一个 git hooks工具(git的钩子工具,可以在特定实际执行特…...
将jar安装到Maven本地仓库中
将jar安装到Maven本地仓库中 1. 使用 mvn install:install-file 命令模版示例 2.项目中添加依赖 将一个 .jar 文件安装到 Maven 本地仓库中是一个常见的操作,尤其是在你想要在本地测试一个尚未发布到中央仓库的库时。以下是如何将 .jar 文件安装到 Maven 本地仓库的…...
Spring 和 Spring MVC 的关系是什么?
Spring和Spring MVC的关系就像是“大家庭和家里的小书房”一样。 Spring是一个大家庭,提供了各种各样的功能和服务,比如管理Bean的生命周期、事务管理、安全性等,它是企业级应用开发的全方位解决方案。这个大家庭里有很多房间,每个…...
Ollama ModelFile(模型文件)
1. 什么是 Modelfile? Modelfile 是 Ollama 的配置文件,用于定义和自定义模型的行为。通过它,你可以: 基于现有模型(如 llama2、mistral)创建自定义版本 调整生成参数(如温度、重复惩罚&#…...
基于python深度学习遥感影像地物分类与目标识别、分割实践技术应用
我国高分辨率对地观测系统重大专项已全面启动,高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成,将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB,遥感大数据时…...
(蓝桥杯——10. 小郑做志愿者)洛斯里克城志愿者问题详解
题目背景 小郑是一名大学生,她决定通过做志愿者来增加自己的综合分。她的任务是帮助游客解决交通困难的问题。洛斯里克城是一个六朝古都,拥有 N 个区域和古老的地铁系统。地铁线路覆盖了树形结构上的某些路径,游客会询问两个区域是否可以通过某条地铁线路直达,以及有多少条…...
基于 Ollama 工具的 LLM 大语言模型如何部署,以 DeepSeek 14B 本地部署为例
简简单单 Online zuozuo :本心、输入输出、结果 文章目录 基于 Ollama 工具的 LLM 大语言模型如何部署,以 DeepSeek 14B 本地部署为例前言下载 Ollama实际部署所需的硬件要求设置 LLM 使用 GPU ,发挥 100% GPU 性能Ollama 大模型管理命令大模型的实际运行资源消耗基于 Ollam…...
大模型工具大比拼:SGLang、Ollama、VLLM、LLaMA.cpp 如何选择?
简介:在人工智能飞速发展的今天,大模型已经成为推动技术革新的核心力量。无论是智能客服、内容创作,还是科研辅助、代码生成,大模型的身影无处不在。然而,面对市场上琳琅满目的工具,如何挑选最适合自己的那…...
【05】密码学与隐私保护
5-1 零知识证明 零知识证明介绍 零知识证明的概念 设P(Prover)表示掌握某些信息,并希望证实这一事实的实体,V(Verifier)是验证这一事实的实体。 零知识证明是指P试图使V相信某一个论断是正确的,但却不向…...
Flink SQL与Doris实时数仓Join实战教程(理论+实例保姆级教程)
目录 第一章:Regular Joins 深度解析 1.1 核心原理与适用场景 1.2 电商订单 - 商品实时关联案例 1.2.1 数据流设计 1.2.2 Doris 表设计优化 1.2.3 性能调优要点 第二章:Interval Joins 实战应用 2.1 时间区间关联原理 2.2 优惠券使用有效性验证 2.2.1 业务场景说明 …...
DeepSeek 助力 Vue 开发:打造丝滑的范围选择器(Range Picker)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
68页PDF | 数据安全总体解决方案:从数据管理方法论到落地实践的全方位指南(附下载)
一、前言 这份报告旨在应对数字化转型过程中数据安全面临的挑战,并提供全面的管理与技术体系建设框架。报告首先分析了数字化社会的发展背景,强调了数据安全在国家安全层面的重要性,并指出数据安全风险的来源和防护措施。接着,报…...
【Github每日推荐】-- 2024 年项目汇总
1、AI 技术 项目简述OmniParser一款基于纯视觉的 GUI 智能体,能够准确识别界面上可交互图标以及理解截图中各元素语义,实现自动化界面交互场景,如自动化测试、自动化操作等。ChatTTS一款专门为对话场景设计的语音生成模型,主要用…...
【Spring详解一】Spring整体架构和环境搭建
一、Spring整体架构和环境搭建 1.1 Spring的整体架构 Spring框架是一个分层架构,包含一系列功能要素,被分为大约20个模块 Spring核心容器:包含Core、Bean、Context、Expression Language模块 Core :其他组件的基本核心ÿ…...
Spring Boot(8)深入理解 @Autowired 注解:使用场景与实战示例
搞个引言 在 Spring 框架的开发中,依赖注入(Dependency Injection,简称 DI)是它的一个核心特性,它能够让代码更加模块化、可测试,并且易于维护。而 Autowired 注解作为 Spring 实现依赖注入的关键工具&…...
Machine Learning:Optimization
文章目录 局部最小值与鞍点 (Local Minimum & Saddle Point)临界点及其种类判断临界值种类 批量与动量(Batch & Momentum)批量大小对梯度下降的影响动量法 自适应学习率AdaGradRMSPropAdam 学习率调度优化总结 局部最小值与鞍点 (Local Minimum & Saddle Point) 我…...
wordpress get_footer();与wp_footer();的区别的关系
在WordPress中,get_footer() 和 wp_footer() 是两个不同的函数,它们在主题开发中扮演着不同的角色,但都与页面的“页脚”部分有关。以下是它们的区别和关系: 1. get_footer() get_footer() 是一个用于加载页脚模板的函数。它的主…...
Windows Docker运行Implicit-SVSDF-Planner
Windows Docker运行GitHub - ZJU-FAST-Lab/Implicit-SVSDF-Planner: [SIGGRAPH 2024 & TOG] 1. 设置环境 我将项目git clone在D:/Github目录中。 下载ubuntu20.04 noetic镜像 docker pull osrf/ros:noetic-desktop-full-focal 启动容器,挂载主机的D:/Github文…...
设计模式14:职责链模式
系列总链接:《大话设计模式》学习记录_net 大话设计-CSDN博客 1.概述 职责链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许将请求沿着处理者链传递,直到有一个处理者能够处理该请求。这种模式通过…...
Golang GORM系列:GORM并发与连接池
GORM 是一个流行的 Go 语言 ORM(对象关系映射)库,用于简化数据库操作。它支持连接池和并发访问功能,这些功能对于高性能、高并发的应用场景非常重要。本文结合示例详细介绍gorm的并发处理能力,以及如何是哟个连接池提升…...
linux笔记:shell中的while、if、for语句
在Udig软件的启动脚本中使用了while循环、if语句、for循环,其他内容基本都是变量的定义,所以尝试弄懂脚本中这三部分内容,了解脚本执行过程。 (1)while循环 while do循环内容如下所示,在循环中还用了expr…...
【Java】逻辑运算符详解:、|| 与、 | 的区别及应用
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: Java 文章目录 💯前言💯一、基本概念与运算符介绍💯二、短路与与非短路与:&& 与 & 的区别1. &&:短路与(AND)2. …...
Java 设计模式之解释器模式
文章目录 Java 设计模式之解释器模式概述UML代码实现 Java 设计模式之解释器模式 概述 解释器模式(interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。如果一种特定…...
关于前后端分离跨域问题——使用DeepSeek分析查错
我前端使用ant design vue pro框架,后端使用kratos框架开发。因为之前也解决过跨域问题,正常是在后端的http请求中加入中间件,设置跨域需要通过的字段即可,代码如下所示: func NewHTTPServer(c *conf.Server, s *conf…...
Linux下ioctl的应用
文章目录 1、ioctl简介2、示例程序编写2.1、应用程序编写2.2、驱动程序编写 3、ioctl命令的构成4、测试 1、ioctl简介 ioctl(input/output control)是Linux中的一个系统调用,主要用于设备驱动程序与用户空间应用程序之间进行设备特定的输入/…...
Windows 环境下 Grafana 安装指南
目录 下载 Grafana 安装 Grafana 方法 1:使用 .msi 安装程序(推荐) 方法 2:使用 .zip 压缩包 启动 Grafana 访问 Grafana 配置 Grafana(可选) 卸载 Grafana(如果需要) 下载 G…...
【操作系统】操作系统概述
操作系统概述 1.1 操作系统的概念1.1.1 操作系统定义——什么是OS?1.1.2 操作系统作用——OS有什么用?1.1.3 操作系统地位——计算机系统中,OS处于什么地位?1.1.4 为什么学操作系统? 1.2 操作系统的历史1.2.1 操作系统…...
基于SSM+uniapp的鲜花销售小程序+LW示例参考
1.项目介绍 系统角色:管理员、商户功能模块:用户管理、商户管理、鲜花分类管理、鲜花管理、订单管理、收藏管理、购物车、充值、下单等技术选型:SSM,Vue(后端管理web),uniapp等测试环境&#x…...
第3章 .NETCore核心基础组件:3.1 .NET Core依赖注入
3.1.1 什么是控制反转、依赖注入 杨老师在书中进行了一系列的文字阐述,总结一下就是:软件设计模式中有一种叫做【控制反转】的设计模式,而依赖注入是实现这种设计模式的一个很重要的方式。也就是说学习依赖注入,是学习怎样实现控…...
排序与算法:插入排序
执行效果 插入排序的执行效果是这样的: 呃……看不懂吗?没关系,接着往下看介绍 算法介绍 插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,…...
uniapp 打包安卓 集成高德地图
接入高德地图 let vm this;uni.chooseLocation({success: function (res) {// console.log(位置名称: res.name);// console.log(详细地址: res.address);// console.log(纬度: res.latitude);// console.log(经度: res.long…...
python爬虫系列课程2:如何下载Xpath Helper
python爬虫系列课程2:如何下载Xpath Helper 一、访问极简插件官网二、点击搜索按钮三、输入xpath并点击搜索四、点击推荐下载五、将下载下来的文件解压缩六、打开扩展程序界面七、将xpath.crx文件拖入扩展程序界面一、访问极简插件官网 极简插件官网地址:https://chrome.zzz…...
win10系统上的虚拟机安装麒麟V10系统提示找不到操作系统
目录预览 一、问题描述二、原因分析三、解决方案四、参考链接 一、问题描述 win10系统上的虚拟机安装麒麟V10系统提示找不到操作系统,报错:Operating System not found 二、原因分析 国产系统,需要注意的点: 需要看你的系统类…...
基于微信小程序的宿舍报修管理系统设计与实现,SpringBoot(15500字)+Vue+毕业论文+指导搭建视频
运行环境 jdkmysqlIntelliJ IDEAmaven3微信开发者工具 项目技术SpringBoothtmlcssjsjqueryvue2uni-app 宿舍报修小程序是一个集中管理宿舍维修请求的在线平台,为学生、维修人员和管理员提供了一个便捷、高效的交互界面。以下是关于这些功能的简单介绍: …...
分布式同步锁:原理、实现与应用
分布式同步锁:原理、实现与应用 引言1. 分布式同步锁的基本概念1.1 什么是分布式同步锁?1.2 分布式锁的特性 2. 分布式锁的实现方式2.1 基于数据库的分布式锁实现原理优缺点示例 2.2 基于 Redis 的分布式锁实现原理优缺点示例Redlock 算法 2.3 基于 ZooK…...
Chrome多开终极形态解锁!「窗口管理工具+IP隔离插件
Web3项目多开,继ads指纹浏览器钱包被盗后,更多人采用原生chrome浏览器,当然对于新手,指纹浏览器每月成本也是一笔不小开支,今天逛Github发现了这样一个解决方案,作者开发了窗口管理工具IP隔离插件ÿ…...
FreeSwitch的应用类模块
FreeSWITCH 应用类模块(Applications)完整表格 模块名称功能描述mod_callcenter提供呼叫中心功能,支持队列、座席管理、监控等。mod_conference提供多方会议功能,支持音频、视频会议。mod_blacklist提供黑名单功能,阻…...
【蓝桥杯集训·每日一题2025】 AcWing 6123. 哞叫时间 python
6123. 哞叫时间 Week 1 2月18日 农夫约翰正在试图向埃尔茜描述他最喜欢的 USACO 竞赛,但她很难理解为什么他这么喜欢它。 他说「竞赛中我最喜欢的部分是贝茜说 『现在是哞哞时间』并在整个竞赛中一直哞哞叫」。 埃尔茜仍然不理解,所以农夫约翰将竞赛以…...