网站内容设计要求/网络营销五种方法
1、Map集合概述
在Java的集合框架中,Map为双列集合,在Map中的元素是成对以<K,V>键值对的形式存在的,通过键可以找对所对应的值。Map接口有许多的实现类,各自都具有不同的性能和用途。常用的Map接口实现类有HashMap
、Hashtable
、TreeMap
、LinkedHashMap
和ConcurrentHashMap
。
2、Map集合主要特点
- Map中的元素都是以<K,V>键值对的形式存在;
- Map中每个键最多映射到一个值,也就是说通过一个key最多只能获取到一个值;
- Map中的key是无序的、不可重复的;
- Map中的value是无序的、可重复的;
3、HashMap
3.1、HashMap简介
HashMap 是 Java 中一个非常常用的集合类,可以通过key的 HashCode 值来快速访问值,具有很快的访问速度,并且由于存储的键值对是无序的,插入的顺序并不会影响到查询的结果。
在 HashMap 中,允许存储的键为 null,value也可以为null,但只能有一个key 为 null。键值对是通过键的 HashCode 值来存储的,如果多个键的 HashCode 值相同,它们就会被存储在同一个桶中,也就是所谓的哈希桶。每个桶是一个单向链表或双向链表,存储了所有哈希值相同的键值对。当我们向 HashMap 中添加一个键值对时,它会根据键的 HashCode 值计算出一个哈希桶的索引,然后将键值对存储在对应的哈希桶中,并将哈希桶中的链表或双向链表更新为当前节点后面的节点。
HashMap 继承自 AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。
3.2、HashMap底层数据结构
Java 中的 HashMap 底层数据结构主要由数组
、链表
、红黑树
三部分组成,jdk 1.8之前采用数组+链表
,jdk 1.8 采用数组+链表+红黑树的方式。
- 数组(Array):HashMap 内部维护了一个 Entry 数组,用于存储键值对。每个 Entry 包含了一个键对象和一个值对象,它们都是通过哈希函数计算得到的哈希码值作为索引,存放在数组中。
- 链表(Linked List):当多个键的哈希码值相同时,它们会被存储在同一个桶中,也就是所谓的哈希桶。每个桶是一个单向链表或双向链表,存储了所有哈希值相同的键值对,链表是为了解决hash冲突的。
- 红黑树(Tree):当链表的长度超过阈值时,在JDK 1.8 之后这个阈值默认为 8,链表会转换成红黑树。红黑树是一种自平衡的二叉查找树,可以快速查找元素。
3.3、HashMap常见问题
3.3.1、哈希码是什么?
哈希码(Hash Code)是用于计算键的哈希值,以便在存储和查询时使用的。哈希码的计算方式是通过将键的哈希值存储在数组中的一个位置上,这个位置称为哈希码值。当我们向 HashMap 中添加键值对时,HashMap 会使用键的哈希值来计算哈希码值,并将键值对存储在对应的哈希码值的位置上。当我们查询 HashMap 中的键值对时,HashMap 会使用键的哈希码值来计算哈希码值的位置,并在该位置上遍历所有的键值对,直到找到对应的键值对。
3.3.2、为什么哈希码在HashMap中很重要?
哈希码的重要性在于,它可以帮助我们快速地定位键值对在数组中的位置,从而提高 HashMap 的存储和查询效率。如果两个键的哈希码不同,它们会被分配到不同的桶中;如果哈希码相同,就会发生哈希冲突,需要进一步处理。
3.3.3、HashMap中如何处理哈希冲突?
为了解决哈希冲突,HashMap 使用了链地址法,即将哈希桶转换成一个链表或红黑树,存储所有哈希值相同的键值对。当多个键的哈希码值相同时,HashMap 会将它们存储在同一个桶中,并将它们转换成链表或红黑树的形式。当我们查询键值对时,HashMap 会遍历该桶中的所有键值对,直到找到对应的键值对。如果该桶中没有对应的键值对,则说明该键值对不存在,HashMap 会返回 null。
3.3.4、为什么HashMap不是线程安全的?
HashMap 内部使用了数组和链表(或红黑树)来存储键值对,当多个线程同时访问 HashMap 时,可能会出现以下问题:
多线程修改元素出现的不安全
:线程 A 和线程 B 同时修改同一个 HashMap 中的键值对,由于 HashMap 是线程不安全的,当线程 A 修改键值对时,线程 B 也可能在同时修改键值对,导致数据不一致或丢失。多线程并发扩容出现的不安全
:HashMap在达到阈值时需要进行扩容,扩容时需要重新计算Hash值,重新分配存储位置。如果在扩容过程中有多个线程同时进行插入或删除操作,就可能会导致数据结构混乱,还可能会导致Map中链表的尾结点指向头结点造成死循环。
3.3.5、HashMap初始化容量是多少?
在创建 HashMap 对象时,需要传入一个整数参数,表示 HashMap 中桶的数量,默认情况下,该参数为 16。初始化容量的大小会直接影响到 HashMap 的空间利用率和性能。如果初始化容量太小,可能会导致频繁的扩容操作,从而降低性能;如果初始化容量太大,则会导致空间浪费,并且当需要进行扩容时,需要重新计算数组大小,并重新分配内存等,也会消耗一定的系统资源。
3.3.6、HashMap 为什么需要动态扩容?
为了提高 HashMap 的查询效率。当桶中链表或红黑树的长度超过一定阈值时,该阈值默认为初始容量的两倍加上负载因子的值,即 2 * initialCapacity + 0.5f。超过这个阈值会自动进行扩容到之前容量的2倍,阈值也为原来的2倍。扩容时,HashMap 会重新分配一个新的桶数组,并将原来的键值对数据复制到新的桶数组中。新的桶数组的大小通常是原来的两倍,以便容纳更多的键值对数据。由于 HashMap 的扩容操作需要重新计算哈希值,因此在扩容时会导致性能下降。为了尽可能减少扩容带来的性能损失,建议在创建 HashMap 实例时,根据实际需要设置合适的容量大小。
3.3.7、HashMap的加载因子是什么?
在 Java 中的 HashMap 中,加载因子是一个重要的参数,它决定了 HashMap 在初始化时所分配的桶的数量。加载因子的取值范围是 0.75 到 1.0 之间,通常情况下,默认的加载因子是 0.75。
加载因子的作用是控制 HashMap 中桶的数量,当桶的数量达到了加载因子所指定的最大值时,就需要进行扩容操作。加载因子的取值会直接影响到 HashMap 的空间利用率和性能,如果加载因子的取值过小,则会导致频繁的扩容操作,从而降低性能;如果加载因子的取值过大,则会导致空间浪费,并且当需要进行扩容时,需要重新计算数组大小,并重新分配内存等,也会消耗一定的系统资源。
3.3.8、HashMap如何保证key的唯一性?
当存储键值对时,先对key的hashCode值进行比较,如果不同,则认为两个key不相等,会直接插入集合中。如果两个key的hashCode值相同,则会调用equals()方法进行比较,如果equals()方法返回true,则认为两个key相等,则会覆盖掉原来的键值对;否则认为两个key不相等,会两个key会放入到同一个哈希桶中。
3.3.9、HashMap中为什么重写equals方法要重写hashcode方法?
在 Java 中,HashMap 类使用键的哈希值和键对象的equals方法来实现键的唯一性。equals方法用于比较两个对象是否相等,而hashCode方法用于生成键对象的哈希码。当两个对象通过equals方法比较相等时,它们的hashCode方法应该返回相同的值。如果两个对象的equals()方法返回true,但是它们的hashCode()方法返回的哈希码不同,那么它们就会被存在HashMap的不同桶里,导致HashMap无法正确获取对象。
3.3.10、HashMap一般用什么作为key?
在 Java 中的 HashMap 类中,键可以是任何实现了 Comparable 接口的对象。最常用的键类型是字符串。这是因为字符串类型的键可以方便地进行比较和排序,并且可以轻松地进行字符串转换。另外,字符串类型的键还可以方便地进行序列化和反序列化操作,从而方便进行数据传输和存储。其他比较常用的类型如:Integer、Long、String、Object等都可以作为key。
4、Hashtable
4.1、Hashtable 简介
Hashtable 是 Java 中的一个同步的键值对存储容器,它实现了 Map 接口。与 HashMap 不同,Hashtable 是线程安全的,它使用 synchronized 关键字将整张散列表加锁的方式来保证多线程访问时的线程安全性,因此它的运行效率非常低。
Hashtable 的key和value都不能为 null,否则会抛出NullPointerException。
4.2、Hashtable 数据结构组成
HashTable 内部的数据结构主要包括以下几个部分:
- 桶数组:使用一个数组来存储键值对,这个数组长度由初始容量和负载因子决定。当有新的键值对插入时,会通过哈希算法计算出键的索引位置,然后将键值对存储在相应的桶中。
- synchronized 块:由于 HashTable 是线程安全的,因此在多线程环境下使用时需要进行同步操作,以防止不同线程对 HashTable 进行修改操作时发生冲突。为了保证同步操作的有效性,HashTable 使用了 synchronized 块来进行同步控制。
- 链表/红黑树:当 HashTable 中有多个键值对的哈希值相同时,这些键值对会被存储在同一个桶中,形成一个链表或红黑树。当链表的节点数量超过一定阈值时,会将链表转化为红黑树,以提高查找效率。
4.3、Hashtable 底层原理
- 初始大小为11,加载因子为0.75;
- 阈值threshold = initialCapacity * loadFactor;
- 扩容机制为大于阈值threshold就进行扩容;
5、TreeMap
5.1、TreeMap简介
TreeMap 是 Java 中的一个基于红黑树的排序 Map 实现,它实现了 NavigableMap 接口,用于存储有序的键值对。由于红黑树的查找效率比链表要慢一些,因此在键值对数量较多的情况下,使用 TreeMap 可能会影响性能。但是,由于 TreeMap 可以保证键值对的有序性,因此在一些需要按照键进行排序的场景下,使用 TreeMap 是比较合适的。
TreeMap的key不能为 null,value可以为null。
5.2、TreeMap 数据结构组成
TreeMap 内部的数据结构主要包括以下几个部分:
- 红黑树:使用红黑树来实现有序的键值对存储,红黑树是一种自平衡的二叉搜索树,可以保证节点之间的排序关系。
- 排序规则:内部维护了一个比较器,用于定义键的排序规则。当插入键值对时,TreeMap 会根据比较器的返回值来确定键的排序顺序。
- 导航操作:提供了一些导航操作,如 subMap、navigate、climbUp、climbDown 等,用于查找、遍历、上翻、下翻等操作。
6、LinkedHashMap
6.1、LinkedHashMap简介
LinkedHashMap 是 Java 中的一个基于双向链表的 Map 实现,它实现了 Map 接口,用于存储键值对,并支持按照插入顺序和访问顺序进行访问。由于 LinkedHashMap 是基于双向链表实现的,因此它的插入、删除、查找等操作的时间复杂度都是 O(1),性能比较优秀。但是,由于双向链表的数据结构比较简单,因此 LinkedHashMap 的可扩展性比一些基于哈希表实现的集合要好。LinkedHashMap 不支持并发访问,如果需要在多线程环境下使用,需要进行同步控制。
LinkedHashMap 的key可以为 null,value可以为null。
6.2、LinkedHashMap 数据结构组成
LinkedHashMap 内部的数据结构主要包括以下几个部分:
- 双向链表:使用双向链表来存储键值对,每个节点包含前一个节点和后一个节点以及对应的键值对。
- 迭代器:提供了一个迭代器,用于遍历链表中的所有键值对。当迭代器遍历时,会按照插入的顺序来遍历链表。
- 访问顺序: 能够记录键值对的访问顺序,当访问键值对时,LinkedHashMap 会根据访问顺序来返回对应的键值对,从而实现有序的访问。
7、ConcurrentHashMap
7.1、ConcurrentHashMap简介
ConcurrentHashMap 是 Java 中常用的一种并发安全的Map实现,它实现了 Map 接口,内部和 HashMap 一样,都是采用了数组 + 链表 + 红黑树的方式来实现。与hashtable不同,该类不依赖于synchronization去保证线程操作的安全,而是利用分段锁(CAS 锁)来保证数据的安全,支持的并发量相对更高。ConcurrentHashMap 插入、删除、查找等操作的时间复杂度都是 O(1),性能也是比较优秀。但是,由于哈希表的数据结构比较复杂,因此 ConcurrentHashMap 的可扩展性相对一些基于链表的实现集合要差。
ConcurrentHashMap 的key和value都不可以为null。
7.2、ConcurrentHashMap 数据结构组成
ConcurrentHashMap 内部的数据结构主要包括以下几个部分:
- 桶(HashTable):使用桶来存储键值对,桶是一个哈希表,每个桶都包含若干个链表,用于存储键值对。
- 缓存区(Segment):使用缓存区来管理桶,缓存区是一个分段的数组,每个缓存区都包含若干个桶,用于提高并发访问时的性能。
- 分段锁(CAS 锁):使用 CAS 锁来实现并发访问,CAS 锁是一种无锁,不需要占用额外的 CPU 资源,可以提高并发访问时的性能。
7.3、ConcurrentHashMap 主要特点
- 并发安全:支持并发访问,能够保证线程安全,即使在多线程环境下也能够正确地访问键值对。
- 高性能:使用缓存区来管理桶,能够提高并发访问时的性能,同时使用 CAS 锁来实现并发访问,能够避免锁竞争,提高并发访问时的性能。
- 可定制的大小:支持可定制的大小,可以根据实际需要来调整大小,从而达到最佳的性能和空间利用率。
相关文章:

Java集合--Map
1、Map集合概述 在Java的集合框架中,Map为双列集合,在Map中的元素是成对以<K,V>键值对的形式存在的,通过键可以找对所对应的值。Map接口有许多的实现类,各自都具有不同的性能和用途。常用的Map接口实现类有HashMap、Hashtab…...

C语言—每日选择题—Day48
第一题 1. 已知宏定义: #define M y*y3*y , 则表达式 s3*M4*My*M 预处理阶段后的结果是 A:s3*(y*y3*y)4*(y*y3*y)y*(y*y3*y) B:s3*(y*y)3*y4*(y*y)3*yy*(y*y)3*y C:s3*y*y3*y4*y*y3*yy*y*y3*y D:s3*(y*y)(3…...

华为OD试题七(IPv4地址转换成整数、比赛的冠亚季军)
1. IPv4地址转换成整数 示例代码: #测试数据 s1 "100#101#1#5"def fun(s):s_list s.split("#")# 转化成十六进制数 左边补零s_16_list [hex(int(_))[2:].zfill(2) for _ in s_list]s_16_str .join(s_16_list)return int(s_16_str,16) r f…...

SVN优缺点详解及版本控制系统选型建议
Subversion (SVN)是目前可用的众多版本控制选项之一。本篇文章将全面概述什么是 SVN、SVN的历史、SVN存储库是什么,以及在切换到SVN之前您应该谨慎考虑的潜在问题。 什么是Subversion(SVN)? Subversion软件,也称为SV…...

自己动手写数据库: select 查询语句对应查询树的构造和执行
首先我们需要给原来代码打个补丁,在SelectScan 结构体初始化时需要传入 UpdateScan 接口对象,但很多时候我们需要传入的是 Scan 对象,因此我们需要做一个转换,也就是当初始化 SelectScan 时,如果传入的是 Scan 对象&am…...

扬声器(喇叭)
扬声器(喇叭) 电子元器件百科 文章目录 扬声器(喇叭)前言一、扬声器(喇叭)是什么二、扬声器(喇叭)的类别三、扬声器(喇叭)的应用场景四、扬声器(喇叭)的作用原理总结前言 扬声器广泛应用于音响系统、公共广播系统、汽车音响、电视、电脑和移动设备等各种电子设备…...

汇总大厂-校招/社招 Java面试题--持续补充更新中-大家别光收藏,要看起来,巩固基础,就是干呀!
** 接上篇-汇总大厂-校招/社招 Java面试题(补充) ** markdown文件。持续更新中(阿里、腾讯、网易、美团、京东、华为、快手、字节…) 上面这篇也结合着看啊,通宵给整理出来的。 如需下载整套资料。关注公众号后台。…...

六. 函数
基本使用 ts与js一样拥有具名函数和匿名函数两种函数类型。但是ts的函数需要提前定义好参数类型以及函数的返回值类型。 具名函数 function add(num1: number, num2: number):number {return num1 num2 }匿名函数 匿名函数的定义相对麻烦,我们需要提前定义函数的…...

SpringBoot的Starter自动化配置,自己编写配置maven依赖且使用及短信发送案例
目录 一、Starter机制 1. 是什么 2. 有什么用 3. 应用场景 二、短信发送案例 1. 创建 2. 配置 3. 编写 4. 形成依赖 6. 其他项目的使用 每篇一获 一、Starter机制 1. 是什么 SpringBoot中的starter是一种非常重要的机制(自动化配置),能够抛弃以前繁杂…...

<蓝桥杯软件赛>零基础备赛20周--第9周--前缀和与差分
报名明年4月蓝桥杯软件赛的同学们,如果你是大一零基础,目前懵懂中,不知该怎么办,可以看看本博客系列:备赛20周合集 20周的完整安排请点击:20周计划 每周发1个博客,共20周(读者可以按…...

LeetCode-2487. 从链表中移除节点【栈 递归 链表 单调栈】
LeetCode-2487. 从链表中移除节点【栈 递归 链表 单调栈】 题目描述:解题思路一:可以将链表转为数组,然后从后往前遍历,遇到大于等于当前元素的就入栈,最终栈里面的元素即是最终的答案。解题思路二:递归&am…...

Redisson分布式锁原理分析
1.Redisson实现分布式锁 在分布式系统中,涉及到多个实例对同一资源加锁的情况,传统的synchronized、ReentrantLock等单进程加锁的API就不再适用,此时就需要使用分布式锁来保证多服务之间加锁的安全性。 常见的分布式锁的实现方式有ÿ…...

【Linux】:线程(二)互斥
互斥与同步 一.线程的局部存储二.线程的分离三.互斥1.一些概念2.上锁3.锁的原理4.死锁 一.线程的局部存储 例子 可以看到全局变量是所有线程共享的,如果我们想要每个线程都单独访问g_val怎么办呢?其实我们可以在它前面加上__thread修饰。 这就相当于把g…...

vscode报错Pylance client: couldn‘t create connection to server.
问题描述: 一打开vscode,右下角就弹报错,Pylance client: couldn’t create connection to server.,让我打开output,打开后似乎是在说连不上server 因为连不上server,所以我的python代码没法解析࿰…...

智能优化算法应用:基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.萤火虫算法4.实验参数设定5.算法结果6.参考文…...

MacOS多屏状态栏位置不固定,程序坞不小心跑到副屏
目录 方式一:通过系统设置方式二:鼠标切换 MacOS多屏状态栏位置不固定,程序坞不小心跑到副屏 方式一:通过系统设置 先切换到左边 再切换到底部 就能回到主屏了 方式二:鼠标切换 我的两个屏幕放置位置如下 鼠标在…...

Python:pipdeptree 语法介绍
相信大家在按照一些包的时候经常会碰到版本不兼容,但是又不知道版本之间的依赖关系,今天给大家介绍一个工具:pipdeptree pipdeptree 是一个 Python 包,用于查看已安装的 pip 包及其依赖关系。它以树形结构展示包之间的依赖关系&am…...

【问题处理】—— lombok 的 @Data 大小写区分不敏感
问题描述 今天在项目本地编译的时候,发现有个很奇怪的问题,一直提示某位置找不到符号, 但是实际在Idea中显示确实正常的,一开始以为又是IDEA的故障,所以重启了IDEA,并执行了mvn clean然后重新编译。但是问…...

跟着我学Python基础篇:08.集合和字典
往期文章 跟着我学Python基础篇:01.初露端倪 跟着我学Python基础篇:02.数字与字符串编程 跟着我学Python基础篇:03.选择结构 跟着我学Python基础篇:04.循环 跟着我学Python基础篇:05.函数 跟着我学Python基础篇&#…...

Tomcat部署(图片和HTML等)静态资源时遇到的问题
文章目录 Tomcat部署静态资源问题图中HTML代码启动Tomcat后先确认Tomcat是否启动成功 Tomcat部署静态资源问题 今天,有人突然跟我提到,使用nginx部署静态资源,如图片。可以直接通过url地址访问,为什么他的Tomcat不能通过这样的方…...

在接触新的游戏引擎的时候,如何能快速地熟悉并开发出一款新游戏?
引言 大家好,今天分享点个人经验。 有一定编程经验或者游戏开发经验的小伙伴,在接触新的游戏引擎的时候,如何能快速地熟悉并开发出一款新游戏? 利用现成开发框架。 1.什么是开发框架? 开发框架,顾名思…...

计网 - TCP四次挥手原理全曝光:深度解析与实战演示
文章目录 Pre导图过程分析抓包实战第一次挥手 【FIN ACK】第二次挥手 【ACK】第三次挥手 【FINACK】第四次挥手 【ACK】 小结 Pre 计网 - 传输层协议 TCP:TCP 为什么握手是 3 次、挥手是 4 次? 计网 - TCP三次握手原理全曝光:深度解析与实战…...

个人养老金知多少?
个人养老金政策你了解吗?税优政策你知道吗?你会计算能退多少税吗?… 点这里看一看...

gpt3、gpt2与gpt1区别
参考:深度学习:GPT1、GPT2、GPT-3_HanZee的博客-CSDN博客 Zero-shot Learning / One-shot Learning-CSDN博客 Zero-shot(零次学习)简介-CSDN博客 GPT1、GPT2、GPT3、InstructGPT-CSDN博客 目录 gpt2与gpt1区别: gp…...

PyQt6 QDateEdit日期控件
锋哥原创的PyQt6视频教程: 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计39条视频,包括:2024版 PyQt6 Python桌面开发 视频教程(无废话…...

【无线网络技术】——无线城域网(学习笔记)
📖 前言:无线城域网(WMAN)是指在地域上覆盖城市及其郊区范围的分布节点之间传输信息的本地分配无线网络。能实现语音、数据、图像、多媒体、IP等多业务的接入服务。其覆盖范围的典型值为3~5km,点到点链路的覆盖可以高达…...

RK3568平台 OTA升级原理
一.前言 在迅速变化和发展的物联网市场,新的产品需求不断涌现,因此对于智能硬件设备的更新需求就变得空前高涨,设备不再像传统设备一样一经出售就不再变更。为了快速响应市场需求,一个技术变得极为重要,即OTA空中下载…...

mysql迁移步骤
MySQL迁移是指将MySQL数据库从一台服务器迁移到另一台服务器。这可能是因为您需要升级服务器、增加存储空间、提高性能或改变数据库架构。 以下是MySQL迁移的一般步骤: 以上是MySQL迁移的一般步骤,具体步骤可能因您的环境和需求而有所不同。在进行迁移之…...

计算机网络应用层(期末、考研)
计算机网络总复习链接🔗 目录 DNS域名服务器域名解析过程分类递归查询(给根域名服务器造成的负载过大,实际中几乎不用)迭代查询 域名缓存(了解即可)完整域名解析过程采用UDP服务 FTP控制连接与数据连接 电…...

Jenkins离线安装部署教程简记
前言 在上一篇文章基于Gitee实现Jenkins自动化部署SpringBoot项目中,我们了解了如何完成基于Jenkins实现自动化部署。 对于某些公司服务器来说,是不可以连接外网的,所以笔者专门整理了一篇文章总结一下,如何基于内网直接部署Jen…...