【Java】HashMap、HashTable和ConcurrentHashMap的区别

news2024/11/15 23:58:03

在这里插入图片描述

文章目录

  • 区别
  • 一、HashMap
    • 1.1基本定义与特性
    • 1.2工作原理与实现
    • 1.3常用方法
    • 1.4性能与优化
  • 二、HashTable
  • 三、ConcurrentHashMap
    • 3.1基本特点
    • 3.2实现原理
    • 3.3常用方法
    • 3.4适用场景
    • 3.5性能优化

HashTable、HashMap和ConcurrentHashMap之间的区别主要体现在线程安全、继承关系与实现接口、对null值的处理、性能以及数据结构等几个方面。以下是对这三者之间区别的详细分析:

区别

项目HashMapHashTableConcurrentHashMap
null键允许(仅能有一个)不允许允许(仅能有一个)
null值允许不允许允许
性能高(单线程下最高)多线程下优于HashTable
数据结构数组+链表+红黑树数组+链表数组+链表+红黑树
继承关系AbstractMap类Dictionary类AbstractMap类
实现接口实现了Map接口Cloneable接口和Serializable接口实现了Map接口实现了Map接口、Cloneable接口和Serializable接口
线程安全不安全安全安全
同步方式synchronized同步方法1.7版本:基于segment分段锁机制,基于ReentrantLock实现;1.8版本:基于CAS+synchronized实现,空节点插入使用CAS,有Node节点则使用synchronized加锁

一、HashMap

HashMap是Java中的一种基于哈希表实现的数据结构,它实现了Map接口并允许使用null键和null值。

1.1基本定义与特性

基于哈希表: HashMap是基于哈希表实现的,通过哈希函数将键映射到索引位置,实现快速查找。
允许null键和值: 与HashTable不同,HashMap允许使用null作为键和值。
非线程安全: HashMap不是线程安全的,因此在多线程环境下使用时需要注意数据一致性问题。

1.2工作原理与实现

哈希函数: HashMap使用哈希函数将键转换为索引,该函数需要满足确定性、高效性和散列性。
冲突解决: 采用链地址法处理哈希冲突,即多个键哈希到同一个索引时,它们会被链接到一个链表中。
动态扩容: 当元素数量超过当前容量的阈值时,HashMap会进行rehashing,创建一个新的数组,并将原数组中的元素重新哈希到新的数组中。

1.3常用方法

put(K key, V value): 向HashMap中添加一个键值对。
get(Object key): 根据键获取对应的值。
remove(Object key): 删除HashMap中指定的键值对。
size(): 返回HashMap中键值对的数量。
isEmpty(): 判断HashMap是否为空。
keySet(): 返回HashMap中所有键的集合。
values(): 返回HashMap中所有值的集合。
entrySet(): 返回HashMap中所有键值对组成的集合。

1.4性能与优化

时间复杂度: HashMap的查找、插入和删除操作的平均时间复杂度为O(1),但在哈希冲突严重时,性能会下降。
链接: 【哈希表】为什么哈希表的插入/删除/查找时间复杂度为O(1)

初始容量与加载因子: 合理设置HashMap的初始容量和加载因子可以提高性能。初始容量是HashMap创建时分配的数组大小,加载因子是触发扩容的阈值。
红黑树优化: 在JDK 1.8及以后的版本中,当链表长度超过一定阈值时,HashMap会将链表转换为红黑树以提高查找性能。

总之,HashMap是一种高效且灵活的数据结构,适用于需要快速查找键值对的场景。在使用时需要注意其非线程安全的特性,并在必要时采取适当的同步措施。

二、HashTable

HashTable(哈希表)是一种根据关键码值直接进行访问的数据结构。它通过特定的哈希函数将关键码值映射到表中的一个位置,以加快数据查找的速度。

  1. HashTable同样是基于哈希表实现,存储的数据同样为key-value键值对,其内部也是通过单链表解决哈希冲突的,容量不足时,同样会自动扩容;

  2. 线程安全,可以用于多线程场景。它的线程安全实现方式是:所有的方法都使用synchronized加锁,像一些读操作不存在线程不安全问题,所以全部方法加锁导致了效率低下。

  3. 现在已经被丢了不再使用了。不涉及线程安全问题时使用HashMap,要保证线程安全时,使用ConcurrentHashMap。

三、ConcurrentHashMap

ConcurrentHashMap是Java集合框架中的一个类,它是HashMap的一个线程安全版本,专为高并发场景设计

3.1基本特点

线程安全: ConcurrentHashMap通过特殊的锁机制和数据结构来确保线程安全,使得多个线程可以并发地读写不同的数据段,而不需要额外的同步措施。

高并发性能: 由于采用了分段锁机制(在Java 8之前)或更精细的锁策略(如CAS和synchronized在Java 8及之后),ConcurrentHashMap能够支持多个线程同时访问不同的数据段,从而提高了并发性能。

支持高效的读操作: 在没有竞争的情况下,读操作几乎没有性能损耗,因为它们可以并行执行。

不允许null键或值: 与HashMap不同,ConcurrentHashMap不允许键或值为null。

3.2实现原理

分段锁机制(Java 7及之前): ConcurrentHashMap在内部将数据分为多个段(Segment),每个段都有自己的锁。当一个线程访问某个段时,它只会锁定该段,而不会锁定整个ConcurrentHashMap。这使得多个线程可以同时访问不同的段,从而提高了并发性能。

更精细的锁策略(Java 8及之后): 在Java 8中,ConcurrentHashMap的实现进行了改进,不再使用分段锁,而是采用了CAS操作和synchronized关键字来实现更精细的锁控制,进一步提高了并发性能。

3.3常用方法

ConcurrentHashMap提供了一系列与HashMap相似的方法,如put、get、remove等,这些方法都是线程安全的。
此外,它还提供了一些原子操作,如putIfAbsent、remove、replace等。

3.4适用场景

ConcurrentHashMap适用于需要在线程安全的环境下使用HashMap的场景,特别是需要实现高并发下的数据访问控制的场景
例如,在多线程环境中记录日志信息时,可以使用ConcurrentHashMap来存储日志数据,以确保数据的一致性和安全性。

3.5性能优化

Java 8对ConcurrentHashMap进行了一些性能优化,包括利用CAS操作替换了之前的Synchronized关键字来减少锁的争用等。这些优化进一步提高了ConcurrentHashMap的并发性能。


以上就是本文所有内容,如果对你有帮助的话,点赞收藏支持一下吧!💞💞💞

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

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

相关文章

(2024|ICLR,变分扩散模型(VDM),可学习编码器,时间相关的均值函数)DiffEnc:使用学到的编码器进行变分扩散

DiffEnc: Variational Diffusion with a Learned Encoder 公和众和号:EDPJ(进 Q 交流群:922230617 或加 VX:CV_EDPJ 进 V 交流群) 目录 0. 摘要 2. 变分扩散模型的基础 3. DiffEnc 4. 编码器和生成模型的参数化 …

Linux--地址空间

目录 看一个现象 基本概念 细节问题--理解它 1.如何理解地址空间? 2.为什么要有地址空间? 3. 进一步了解页表和写时拷贝 4.如何理解虚拟地址? 看一个现象 先通过一段代码,看一看现象 int g_val 100;int main() {printf(&quo…

Linux 认识与学习Bash——2

1 read 从键盘读取变量的值 read 后面不带变量,那么默认会给REPLY变量赋值 #!/bin/bash echo -n "请输入你的名字:" read name echo "欢迎您 $name" echo "----------------"echo -n "请输入你的名字2:&q…

我与深拷贝

前言 最近在掘金读到了一篇文章《Radash 能取代 Lodash???真幽默 - 掘金》,文章的评论区讨论起了深拷贝。"深拷贝" 我的"老朋友",还记得在学习我人生中的第二道面试题的时候认识了它,…

CSS 画一个三角形

一、前言 在前端开发的时候,我们有时候会需要用到一个三角形的形状,比如地址选择或者播放器里面播放按钮 通常情况下,我们会使用图片或者svg去完成三角形效果图,但如果单纯使用css如何完成一个三角形呢? 实现过程似…

物理学视角讲解diffusion生成模型——隐扩散模型

https://zhuanlan.zhihu.com/p/692996885 https://zhuanlan.zhihu.com/p/693255617 前面两篇文章介绍了扩散过程,同时实现了1维、2维混合高斯扩散、逆扩散,通过模型预测得分函数来实现逆扩散推理。这个章节介绍工业界使用的文本生成图扩撒模型&#xff1…

基于SSM+Jsp+Mysql的多人命题系统

开发语言:Java框架:ssm技术:JSPJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包…

frp改造Windows笔记本实现家庭版免费内网穿透

文章目录 前言frp原理Windows服务端IP检验IP固定软件下载端口放行端口映射开机启动 NAS客户端端口查询软件下载端口检验穿透测试自启设置 Ubuntu客户端软件下载后台启动 后记 前言 之前一直用花生壳远程控制一个服务器,但最近内网的网络策略似乎发生了变化&#xf…

InfiniGate自研网关实现思路二

5.HTTP请求参数解析 解析 HTTP 网络请求的参数信息,包括;GET/POST,以及应对不同 Content-Type 类型的处理。 HTTP 接口请求的参数需要解析成可以匹配到 RPC 接口的入参信息,所以通常为了方便控制一般只支持 RPC 接口单个对象入参…

「sentinel」流量控制组件的应用

「sentinel」流量控制组件的应用 Sentinel版本QPS 一、初识Sentinel1、Sentinel2、Sentinel 和 Hystrix对比3、雪崩问题 二、环境搭建1、下载安装Sentinel2、微服务整合Sentinel 三、流量控制1、簇点链路2、流控设置3、流控模式直接关联链路 4、流控效果流控效果解释 四、热点限…

C#通用类库封装实战

数据库查询 特性方式获取数据库列的别名 数据库更新 使用简单工厂配置的方式

C++ stl容器stack,queue,priority_queue的底层模拟实现

目录 前言: 文档借鉴:Reference - C Reference 1.deque a.deque的结构特点: b.deque的迭代器结构: c.面试题: 2.stack 3.queue 4.仿函数 5.priority_queue 总结: 前言: 本篇一共简单…

【QT学习】8.qt事件处理机制,事件过滤器,自定义事件

1.qt事件处理机制 事件处理: 当用户移动鼠标的时候 ,创建一个 鼠标移动事件对象 然后把这个对象放到 事件队列里面去,事件管理器 从队列中 取出事件,然后 调用其对应的事件处理函数。 多态机制: &#x…

靠谱的婚恋平台有哪些?青藤之恋、二狗、百合网、珍爱网等深度测评

哇塞,恋爱和结婚对于年轻人来讲可是超级重要的大事呢!不过呀,找到一个稳稳当当的婚恋平台可不简单哟!那么,到底哪个婚恋平台最靠得住呢? 丛丛: 这可是我用了好久好久的脱单交友小程序嘞&#xf…

MySQL中explain的用法

执行结果各字段的含义 EXPLAIN SQL语句 如: EXPLAIN SELECT * FROM test 执行结果: 列名描述id在一个大的查询语句中每个SELECT关键字都对应一个 唯一的idselect_typeSELECT关键字对应的那个查询的类型table表名partitions匹配的分区信息type针对单表…

机器学习预测汽车油耗效率 MPG

流程 数据获取导入需要的包引入文件,查看内容划分训练集和测试集调用模型查看准确率 数据获取 链接:https://pan.baidu.com/s/1KeIJykbcVpsfEk0xjhiICA?pwd30oe 提取码:30oe --来自百度网盘超级会员V1的分享导入需要的包 import pandas as pd imp…

【Spring Boot】掌握Spring Boot:深入解析配置文件的使用与管理

💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录文章:【Spring Boot】掌握Spring Boot:深入解析配置文件的使用与管理 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 Spring Boot 配置文件一. 配置文…

重新总结一下以前写过的“波特率”!单片机常见的通信速率分析!

文章目录 如题以前文章新的总结如题 波特率是单片机中描述通信速率的一个单位,比如串口通信、SPI通信、IIC通信、LIN通信、CAN通信等等,现在重新总结一下涉及到波特率的一些知识点。 以前文章 上面是存储的单位换算方式 这是通信速率的换算方式 新的总结 波特率的英文是…

画家-qt-surce

void GraphicView::paintEvent(QPaintEvent *pe) { QPainter painter(viewport()); painter.setRenderHint(QPainter::SmoothPixmapTransform);//升级画家 painter.drawImage(rect(),musicImage); } 分析: 这段代码是用于绘制图形视图的部分。 1. void GraphicV…

JavaCard学习笔记: CAP Component 之 Class Component

文章目录 整体结构tag和size字段signature_pool_length和signature_pooltype_descriptor结构导入类型编码导入项签名示例导入类导入数组导入远程方法 interfaces[]interface_info结构flagsinteface_countsuperinterfacesinterface_name class_info_compact classes[]结构flagsi…