当前位置: 首页 > news >正文

HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。

HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。

HashMap相关问题

1、你用过HashMap吗?什么是HashMap?你为什么用到它?用过,HashMap是基于哈希表的Map接口的非同步实现,
它允许null键和null值,且HashMap依托于它的数据结构的设计
,存储效率特别高,这是我用它的原因2、你知道HashMap的工作原理吗?你知道HashMapget()方法
的工作原理吗?上面两个问题属于同一答案的问题HashMap是基于hash算法实现的,通过put(key,value)
存储对象到HashMap中,也可以通过get(key)HashMap中获取对象。
当我们使用put的时候,首先HashMap会对key的hashCode()的值
进行hash计算,根据hash值得到这个元素在数组中的位置,
将元素存储在该位置的链表上。当我们使用get的时候,
首先HashMap会对key的hashCode()的值进行hash计算,
根据hash值得到这个元素在数组中的位置,将元素从该位置上的链表中取出3、当两个对象的hashcode相同会发生什么?hashcode相同,说明两个对象HashMap数组的同一位置上,
接着HashMap会遍历链表中的每个元素,
通过key的equals方法来判断是否为同一个key,
如果是同一个key,则新的value会覆盖旧的value,
并且返回旧的value。如果不是同一个key,
则存储在该位置上的链表的链头4、如果两个键的hashcode相同,你如何获取值对象?遍历HashMap链表中的每个元素,并对每个key进行hash计算,
最后通过get方法获取其对应的值对象5、如果HashMap的大小超过了负载因子(load factor)定义的容量,
怎么办?负载因子默认是0.75HashMap超过了负载因子定义的容量,
也就是说超过了(HashMap的大小*负载因子)这个值,
那么HashMap将会创建为原来HashMap大小两倍的数组大小,
作为自己新的容量,这个过程叫resize或者rehash6、你了解重新调整HashMap大小存在什么问题吗?当多线程的情况下,可能产生条件竞争。当重新调整HashMap大小的时候,
确实存在条件竞争,如果两个线程都发现HashMap需要重新调整大小了,
它们会同时试着调整大小。在调整大小的过程中,
存储在链表中的元素的次序会反过来,
因为移动到新的数组位置的时候,
HashMap并不会将元素放在LinkedList的尾部,而是放在头部,
这是为了避免尾部遍历(tail traversing)。
如果条件竞争发生了,那么就死循环了7、我们可以使用自定义的对象作为键吗?可以,只要它遵守了equals()hashCode()方法的定义规则,
并且当对象插入到Map中之后将不会再改变了。
如果这个自定义对象时不可变的,那么它已经满足了作为键的条件,
因为当它创建之后就已经不能改变了。

HashSet与HashMap区别

HashMap实现了Map接口 
HashSet实现了Set接口HashMap储存键值对 
HashSet仅仅存储对象HashMap使用put()方法将元素放入map中 
HashSet使用add()方法将元素放入set中HashMap中使用键对象来计算hashcode值 
HashSet使用成员对象来计算hashcode值HashMap比较快,因为是使用唯一的键来获取对象 
HashSetHashMap来说比较慢

HashTable与HashMap的区别

Hashtable方法是同步的 
HashMap方法是非同步的Hashtable基于DictionaryHashMap基于AbstractMap,而AbstractMap基于Map接口的实现Hashtable中key和value都不允许为null,遇到null,
直接返回 NullPointerException 
HashMap中key和value都允许为null,遇到key为null的时候,
调用putForNullKey方法进行处理,而对value没有处理Hashtable中hash数组默认大小是11,扩充方式是old*2+1 
HashMap中hash数组的默认大小是16,而且一定是2的指数

LinkedHashMap的有序性

LinkedHashMap底层使用哈希表与双向链表来保存所有元素,
它维护着一个运行于所有条目的双向链表
(如果学过双向链表的同学会更好的理解它的源代码),
此链表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序 
1.按插入顺序的链表:在LinkedHashMap调用get方法后,
输出的顺序和输入时的相同,这就是按插入顺序的链表,
默认是按插入顺序排序2.按访问顺序的链表:在LinkedHashMap调用get方法后,
会将这次访问的元素移至链表尾部,
不断访问可以形成按访问顺序排序的链表。简单的说,
按最近最少访问的元素进行排序(类似LRU算法)

我们可以通过例子来理解我们上面所说的LinkedHashMap的插入顺序和访问顺序

public static void main(String[] args) {Map<String, String> map = new HashMap<String, String>();map.put("apple", "苹果");map.put("watermelon", "西瓜");map.put("banana", "香蕉");map.put("peach", "桃子");Iterator iter = map.entrySet().iterator();while (iter.hasNext()) {Map.Entry entry = (Map.Entry) iter.next();System.out.println(entry.getKey() + "=" + entry.getValue());}
}

上面是简单的HashMap代码,通过控制台的输出,我们可以看到HashMap是没有顺序的

banana=香蕉
apple=苹果
peach=桃子
watermelon=西瓜

我们现在将HashMap换成LinkedHashMap,其他代码不变

Map<String, String> map = new LinkedHashMap<String, String>();

看一下控制台的输出

apple=苹果
watermelon=西瓜
banana=香蕉
peach=桃子

我们可以看到,其输出顺序是完成按照插入顺序的,也就是我们上面所说的保留了插入的顺序。下面我们修改一下代码,通过访问顺序进行排序。

public static void main(String[] args) {Map<String, String> map = new LinkedHashMap<String, String>(16,0.75f,true);map.put("apple", "苹果");map.put("watermelon", "西瓜");map.put("banana", "香蕉");map.put("peach", "桃子");map.get("banana");map.get("apple");Iterator iter = map.entrySet().iterator();while (iter.hasNext()) {Map.Entry entry = (Map.Entry) iter.next();System.out.println(entry.getKey() + "=" + entry.getValue());}
}

代码与之前的相比
1.替换了LinkedHashMap的构造函数,使用三个参数的构造函数,第三个参数传进true就是表明用访问顺序来排序,默认是false(即插入顺序)
2.增加了两句LinkedHashMap的get方法,来表示最近已经访问过这两个元素了

//修改的代码
Map<String, String> map = new LinkedHashMap<String, String>(16,0.75f,true);
......
map.get("banana");
map.get("apple");

看一下控制台的输出结果

watermelon=西瓜
peach=桃子
banana=香蕉
apple=苹果

我们可以看到,顺序是先从最少访问的元素开始遍历(西瓜、桃子),而香蕉、苹果是因为分别调用了get方法,香蕉是最先访问的,所以它的比苹果更少用一些。这也就是我们之前提到过的,LinkedHashMap可以选择按照访问顺序进行排序

LinkedHashMap与HashMap的区别
LinkedHashMap有序的,有插入顺序和访问顺序
HashMap无序的

LinkedHashMap内部维护着一个运行于所有条目的双向链表
HashMap内部维护着一个单链表

什么是ArrayList
ArrayList可以理解为动态数组,它的容量能动态增长,该容量是指用来存储列表元素的数组的大小,随着向ArrayList中不断添加元素,其容量也自动增长
ArrayList允许包括null在内的所有元素
ArrayList是List接口的非同步实现
ArrayList是有序的

ArrayList实现了List接口、底层使用数组保存所有元素,其操作基 本上是对数组的操作ArrayList继承了AbstractList抽象类,它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能ArrayList实现了RandmoAccess接口,即提供了随机访问功能,RandmoAccess是java中用来被List实现,为List提供快速访问功能的,我们可以通过元素的序号快速获取元素对象,这就是快速随机访问ArrayList实现了Cloneable接口,即覆盖了函数clone(),能被克隆 
ArrayList实现了java.io.Serializable接口,意味着ArrayList支持序列化

什么是LinkedList

LinkedList基于链表的List接口的非同步实现
LinkedList允许包括null在内的所有元素
LinkedList是有序的
LinkedList是fail-fast的

LinkedList与ArrayList的区别

LinkedList底层是双向链表
ArrayList底层是可变数组
LinkedList不允许随机访问, 即查询效率低 ArrayList允许随机访问,即查询效率高
LinkedList插入和删除效率快
ArrayList插入和删除效率低

解释一下:

对于随机访问的两个方法,get和set,ArrayList优于LinkedList,因为LinkedList要移动指针
对于新增和删除两个方法,add和remove,LinedList比较占优势,因为ArrayList要移动数据

什么是ConcurrentHashMap

ConcurrentHashMap基于双数组和链表的Map接口的同步实现
ConcurrentHashMap中元素的key是唯一的、value值可重复
ConcurrentHashMap不允许使用null值和null键
ConcurrentHashMap是无序的

为什么使用ConcurrentHashMap

我们都知道HashMap是非线程安全的,当我们只有一个线程在使用HashMap的时候,自然不会有问题,但如果涉及到多个线程,并且有读有写的过程中,HashMap就会fail-fast。要解决HashMap同步的问题,我们的解决方案有

Hashtable

Collections.synchronizedMap(hashMap)
这两种方式基本都是对整个hash表结构加上同步锁,这样在锁表的期间,别的线程就需要等待了,无疑性能不高,所以我们引入ConcurrentHashMap,既能同步又能多线程访问

ConcurrentHashMap的数据结构

ConcurrentHashMap的数据结构为一个Segment数组,Segment的数据结构为HashEntry的数组,而HashEntry存的是我们的键值对,可以构成链表。可以简单的理解为数组里装的是HashMap
在这里插入图片描述
从上面的结构我们可以了解到,ConcurrentHashMap定位一个元素的过程需要进行两次Hash操作,第一次Hash定位到Segment,第二次Hash定位到元素所在的链表的头部,因此,这一种结构的带来的副作用是Hash的过程要比普通的HashMap要长,但是带来的好处是写操作的时候可以只对元素所在的Segment进行加锁即可,不会影响到其他的Segment。正是因为其内部的结构以及机制,ConcurrentHashMap在并发访问的性能上要比Hashtable和同步包装之后的HashMap的性能提高很多。在理想状态下,ConcurrentHashMap 可以支持 16 个线程执行并发写操作(如果并发级别设置为 16),及任意数量线程的读操作

什么是Vector

Vector是基于可变数组的List接口的同步实现
Vector是有序的
Vector允许null键和null值
Vector已经不建议使用了

Vector实现了List接口、底层使用数组保存所有元素,其操作基本上是对数组的操作
Vector继承了AbstractList抽象类,它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能
Vector实现了RandmoAccess接口,即提供了随机访问功能,RandmoAccess是java中用来被List实现,为List提供快速访问功能的,我们可以通过元素的序号快速获取元素对象,这就是快速随机访问
Vector实现了Cloneable接口,即覆盖了函数clone(),能被克隆
Vector实现了java.io.Serializable接口,意味着ArrayList支持序列化

Vector和ArrayList的区别
Vector同步、线程安全的
ArrayList异步、线程不安全

Vector 需要额外开销来维持同步锁,性能慢
ArrayList 性能快

Vector 可以使用Iterator、foreach、Enumeration输出
ArrayList 只能使用Iterator、foreach输出

相关文章:

HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。

HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。 HashMap相关问题 1、你用过HashMap吗&#xff1f;什么是HashMap&#xff1f;你为什么用到它&#xff1f;用过&#xff0c;HashMap是基于哈希表的Map接口的非同步实现&#xff0c; 它允许null键…...

flink学习之广播流与合流操作demo

广播流是什么&#xff1f; 将一条数据广播到所有的节点。使用 dataStream.broadCast() 广播流使用场景&#xff1f; 一般用于动态加载配置项。比如lol&#xff0c;每天不断有人再投诉举报&#xff0c;客服根本忙不过来&#xff0c;腾讯内部做了一个判断&#xff0c;只有vip3…...

PPT架构师架构技能图

PPT架构师架构技能图 目录概述需求&#xff1a; 设计思路实现思路分析1.软素质2.核心输出&#xff08;office输出&#xff09; 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,ma…...

STM32微控制器的低功耗模式

STM32微控制器的低功耗模式(Low-power modes):Sleep mode、Stop mode 和 Standby mode。 1.1 Sleep Mode(睡眠模式): 把STM32微控制器当作一位劳累的工人,他在工作过程中需要短暂的休息。在Sleep模式下,微控制器会关闭一部分电路,减小功耗,但仍然保持对中央处理单…...

tensorflow QAT

tensorflow qat https://www.wpgdadatong.com/tw/blog/detail/70672 在边缘运算的重点技术之中&#xff0c;除了简化复杂的模块构架&#xff0c;来简化参数量以提高运算速度的这项模块轻量化网络构架技术之外。另一项技术就是各家神经网络框架&#xff08;TensorFlow、Pytorc…...

[杂谈]-快速了解LoRaWAN网络以及工作原理

快速了解LoRaWAN网络以及工作原理 文章目录 快速了解LoRaWAN网络以及工作原理1、LoRaWAN网络元素1.1 终端设备&#xff08;End Devices&#xff09;1.2 网关&#xff08;Gateways&#xff09;1.3 网络服务器&#xff08;Net Server&#xff09;1.4 应用服务器&#xff08;Appli…...

MySQL--MySQL表的增删改查(基础)

排序&#xff1a;ORDER BY 语法&#xff1a; – ASC 为升序&#xff08;从小到大&#xff09; – DESC 为降序&#xff08;从大到小&#xff09; – 默认为 ASC SELECT … FROM table_name [WHERE …] ORDER BY column [ASC|DESC], […]; *** update...

Vue中启动提示polyfill缺少-webpack v5版本导致

安装 npm i node-polyfill-webpack-plugin 因为我们的项目使用webpack v5&#xff0c;其中polyfill Node核心模块被删除。所以&#xff0c;我们安装它是为了在项目中访问这些模块 vue.config.js文件 const { defineConfig } require("vue/cli-service"); const No…...

Hugging Face实战-系列教程3:AutoModelForSequenceClassification文本2分类

&#x1f6a9;&#x1f6a9;&#x1f6a9;Hugging Face 实战系列 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在notebook中进行 本篇文章配套的代码资源已经上传 下篇内容&#xff1a; Hugging Face实战-系列教程4&#xff1a;padding与attention_mask ​输出我…...

《TCP/IP网络编程》阅读笔记--Socket类型及协议设置

目录 1--协议的定义 2--Socket的创建 2-1--协议族&#xff08;Protocol Family&#xff09; 2-2--Socket类型&#xff08;Type&#xff09; 3--Linux下实现TCP Socket 3-1--服务器端 3-2--客户端 3-3--编译运行 4--Windows下实现 TCP Socket 4-1--TCP服务端 4-2--TC…...

GitHub使用教程

GitHub使用教程 视频教程一&#xff1a;Github 新手够用指南 | 全程演示&个人找项目技巧放送_哔哩哔哩_bilibili 笔记&#xff1a; README.md编写教程&#xff1a;Typora官方免费版与入门教程__阿伟_的博客-CSDN博客 找开源项目的一些途径 • https://github.com/trendin…...

sql server 分区表

分区表 分区表是在SQL Server 2005之后的版本引入的特性&#xff0c;这个特性允许把逻辑上的一个表在物理上分为很多部分。换句话说&#xff0c;分区表从物理上看是将一个大表分成几个小表&#xff0c;但是从逻辑上看&#xff0c;还是一个大表。 步骤 创建分表区的步骤分为…...

开源许可证概述:GNU, BSD, Apache, MPL, 和 MIT

前言 开源许可证是开源软件分发的基础。它们定义了使用者如何使用&#xff0c;修改&#xff0c;分发开源软件。在这篇文章中&#xff0c;我们将探讨五种常见的开源许可证&#xff1a;GNU通用公共许可证 (GNU GPL)&#xff0c;BSD许可证&#xff0c;Apache许可证&#xff0c;Mo…...

java中log使用总结

目录 一、概述1.1. 核心日志框架1.2 门面日志框架 二、最佳实践2.1 核心日志框架API包2.2 门面日志框架依赖2.3 集成使用2.3.1 集成jcl2.3.2 集成slf4j2.3.2.1 slf4j集成单一框架2.3.2.2 slf4j整合混合框架 三、总结3.1 所有相关包3.1.1 核心日志框架包3.1.2 门面日志框架3.1.3…...

【Java】传输层协议TCP

传输层协议TCP TCP报文格式首部长度保留位32位序列号和32位确认应答号标记ACKSYNFINRSTURGPSH 16位窗口大小16位校验和16位紧急指针选项 TCP特点可靠传输实现机制-确认应答超时重传连接管理机制三次握手四次挥手特殊情况 滑动窗口流量控制拥塞控制延迟应答捎带应答面向字节流粘…...

计算机网络基础知识(非常详细)

1. 网络模型 1.1 OSI 七层参考模型 七层模型&#xff0c;亦称 OSI&#xff08;Open System Interconnection&#xff09;参考模型&#xff0c;即开放式系统互联&#xff0c;是网络通信的标准模型。一般称为 OSI 参考模型或七层模型。 它是一个七层的、抽象的模型体&#xff…...

如何进行SEO优化数据分析?(掌握正确的数据分析方法,让您的网站更上一层楼!)

在互联网时代&#xff0c;SEO优化已经成为了每一个网站运营者必备的技能。而在SEO优化中&#xff0c;数据分析更是至关重要的一环。在本文中&#xff0c;我们将会详细介绍如何正确的进行SEO优化数据分析&#xff0c;让您的网站更上一层楼&#xff01; 数据分析的重要性 数据分…...

Golang不同平台编译的思考

GOOS和GOARCH $GOOS可选值如下&#xff1a; darwin dragonfly freebsd linux netbsd openbsd plan9 solaris windows $GOARCH可选值如下 386 amd64 arm 在编译的时候我们可以根据实际需要对这两个参数进行组合。更详细的说明可以进官网看看 ## http://golang.org/cmd/go http…...

SpringSecurity学习

1.认证 密码校验用户 密码加密存储 Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter {Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}} 我们没有这个配置&#xff0c;默认明文存储, {id}password;实现…...

时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测

时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测 目录 时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 ICEEMDAN-iMPA-BiLSTM功率/风速预测 基于改进的自适应经验模态分解改进海洋捕食者算法双向长短期记忆…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...