hashtable底层
一、单线程环境下
底层:hash表结构 (数组 + 链表)
使用无参构造创建对象时 会默认长度11的数组 加载因子0.75
Hashtable<Object, Object> hashtable = new Hashtable<>();
添加第一个元素
hashtable.put("键","值");
根据键的哈希值计算出应存入的索引 例: 5;然后判断 5索引上是否为 null 如果为null 直接存入元素
添加第二个元素
根据键的哈希值计算出应存入的索引 例: 8;然后判断 8索引上是否为 null 如果为null 直接存入元素
添加第三个元素
根据键的哈希值计算出应存入的索引 例: 5
然后判断 5索引上是否为 null
此时 5 索引上 已经有了一个元素 不为null ,则会调用equals方法比较键的属性值
如果一样,则覆盖,如果不一样,则存入数组,头插的形式,老元素挂在新元素下面 形成链表结构
二、多线程环境下
采用悲观锁的方式
添加元素
多个线程添加元素时 ,线程一进入后 synchronized锁住整个数组 其他线程 等待锁释放 其他操作不变
三、JDK1.8 hashtable的put方法的底层源码
在 JDK 1.8 中,Hashtable 的 put 方法是线程安全的哈希表操作核心方法之一,其源码设计体现了同步机制、哈希冲突解决和动态扩容等关键逻辑。以下是详细的源码解析和实现原理:
1、put 方法源码
关键步骤解析
a、线程安全保证
put 方法被 synchronized 修饰,同一时间仅允许一个线程操作,确保线程安全
缺点:在高并发场景下,同步粒度较粗,可能导致性能瓶颈(相比之下,ConcurrentHashMap 使用分段锁优化)
b、空值检查
强制约束:Hashtable 不允许 key 或 value 为 null,直接抛出 NullPointerException
对比:HashMap 允许 null 键和值,但需特殊处理(如 hashCode 为 0)
c、哈希值计算
通过 key.hashCode() 获取哈希值
哈希修正:hash & 0x7FFFFFFF 将哈希值转为正数(索引必须非负)
d、索引定位
通过 (hash % tab.length) 计算索引(tab.length 是哈希表数组长度)
问题:取模运算可能效率较低(HashMap 使用位运算优化)
e、链表遍历
在计算出的索引位置遍历链表,检查是否存在相同键:
若存在,直接替换旧值并返回旧值
若不存在,调用 addEntry 插入新节点
2、插入新节点(addEntry)
扩容条件:当元素数量 count 超过阈值 threshold(默认 capacity * loadFactor)
头插法:新节点插入链表头部(JDK 1.8 的 HashMap 改为尾插法避免循环链表问题)
3、扩容机制(rehash)
新容量:newCapacity = 2 * oldCapacity + 1(非严格的 2 倍扩容)
重新哈希:所有节点需重新计算索引,并迁移到新数组
四、put方法的整个处理流程分析
put方法的整个处理流程是:计算key的hash值,根据hash值获得key在table数组中的索引位置,然后迭代该key处的Entry链表,若该链表中存在一个这个的key对象,那么就直接替换其value值即可,
否则在将改key-value节点插入该index索引位置处。如下:假设我们现在Hashtable的容量为5,已经存在了(5,5),(13,13),(16,16),(17,17),(21,21)这 5 个键值对,目前他们在Hashtable中的位置如下:
现在,我们插入一个新的键值对,put(16,22),假设key=16的索引为1.但现在索引1的位置有两个Entry了,所以程序会对链表进行迭代。迭代的过程中,发现其中有一个Entry的key和我们要插入的键值对的key相同,
所以现在会做的工作就是将newValue=22替换oldValue=16,然后返回oldValue=16.
然后我们现在再插入一个,put(33,33),key=33的索引为3,并且在链表中也不存在key=33的Entry,所以将该节点头插入链表的第一个位置。
五、总结
设计目标:Hashtable 是早期线程安全哈希表实现,通过方法级同步保证安全
缺点:
锁粒度粗,并发性能差
不支持 null 键值
哈希冲突处理简单(仅链表,无红黑树优化)
适用场景:低并发环境或需要兼容旧代码时(现代开发更推荐 ConcurrentHashMap)
hashtable底层的更多相关文章
- java面试题之HashMap和HashTable底层实现的区别
HashMap和HashTable的区别: 相同点:都是以key和value的形式存储: 不同点: HashMap是不安全的:HashTable线程安全的(使用了synchronized关键字来保证线 ...
- java-vector hashtable过时?
vector hashtable过时? 在用JAVA集合时,IDE提示 vector 以及hashtable被arraylist ,hashmap替代,而前者又是线程同步的,不知道为什么?是效率差了的 ...
- Java中常见数据结构:list与map -底层如何实现
1:集合 2 Collection(单列集合) 3 List(有序,可重复) 4 ArrayList 5 底层数据结构是数组,查询快,增删慢 6 线程不安全,效率高 7 Vector 8 底层数据结构 ...
- HashMap、Hashtable、ConcurrentHashMap的原理与区别
同步首发:http://www.yuanrengu.com/index.php/2017-01-17.html 如果你去面试,面试官不问你这个问题,你来找我^_^ 下面直接来干货,先说这三个Map的区 ...
- 集合各个实现类的底层实现原理 ----- 原文地址:https://blog.csdn.net/qq_25868207/article/details/55259978
ArrayList实现原理要点概括 参考文献: http://zhangshixi.iteye.com/blog/674856l https://www.cnblogs.com/leesf456/p/ ...
- HashMap、Hashtable、ConcurrentHashMap的原理与区别(简述)
HashTable 底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相 ...
- hashMap,hashTable,concurrentHashMap区别
HashTable 底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相 ...
- 面试必备:HashMap、Hashtable、ConcurrentHashMap的原理与区别
同步首发:http://www.yuanrengu.com/index.php/2017-01-17.html 如果你去面试,面试官不问你这个问题,你来找我^_^ 下面直接来干货,先说这三个Map的区 ...
- CurrentHashMap、HashMap、HashTable的区别
HashTable 底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相 ...
- HashMap,HashTable,concurrentHashMap,LinkedHashMap 区别
HashMap 不是线程安全的 HashTable,concurrentHashMap 是线程安全 HashTable 底层是所有方法都加有锁(synchronized) 所以操作起来效率会低 con ...
随机推荐
- .NET中优雅使用Patch: JsonPatch
引言 在现代 Web API 开发中,我们经常需要对资源进行部分更新(Partial Update).传统的 PUT 请求会要求发送整个对象,而 PATCH 请求可以仅发送需要更新的字段.ASP.NE ...
- hibernate基础查询语句使用
hibernate最新文档 项目仓库地址项目201102-hibernateSelect 数据准备 -- 创建数据表 drop table if exists t_book; create table ...
- flutter-路由传值携带中文时,报错
解决方案: 路由采用了第三方:fluro 1 Application.router.navigateTo(context, "/searchresult?word=${Uri.encodeC ...
- Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
Deepseek卡的问题已经有几周了,还有同学没有解决这个问题? 今天就来教大家如何白嫖阿里云的Deepseek-R1满血版,新用户享受100万token额度,相当的富裕,可以随便用了.并且还配用AP ...
- el-radio-group之迷惑操作:label和label
el-radio-group之迷惑操作:label和label 今天学习element-ui的el-radio-group的时候发现el-radio-group的默认值设置无效,但是点击其他单选框可以 ...
- wikidata介绍和查询
Wikidata是一个大型结构化开源知识图,为维基百科等项目提供支持.我们可使用SPARQL(Wikidata官方Tutorial)对其进行查询.SPARQL是一种专为 RDF(Resource ...
- 面试题40. 最小的k个数
地址:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/ <?php /** * 面试题40. 最小的k个数 * 输入整数数组 ...
- Qt个人项目总结 —— MySQL数据库查询与断言
3.Qt项目总结--数据库查询断言问题 问题: 当我使用MySQL数据库的查询操作时, 如果查询的数据在数据库中不存在,那么Qt会直接被干崩溃 但是?为什么呢?不应该是返回if语句中的结果吗,为什么会 ...
- centos7 docker卸载老版本并升级到最新稳定版本
一.前言 docker的版本分为社区版docker-ce和企业版dokcer-ee社,区版是免费提供给个人开发者和小型团体使用的,企业版会提供额外的收费服务,比如经过官方测试认证过的基础设施.容器.插 ...
- 安装Realtek RTL8111/RTL8168网卡驱动详解(error~eth0:no such device)
昨天给linux系统重新编了个内核linux2.6.31.9,进入新版本的内核之后,发现机子上不了网了.好像每次新编译一个内核版本,网卡都会出问题,之前也写过解决网卡问题的blog,不过比较简单,这里 ...