网站首页 > java教程 正文
核心区别总结
特性 | HashMap | Hashtable |
引入版本 | Java 1.2 | Java 1.0 |
线程安全 | 非线程安全 | 线程安全(synchronized方法) |
null值支持 | 允许key和value为null | 不允许key或value为null |
性能 | 更高(无同步开销) | 较低(同步开销) |
继承体系 | 继承AbstractMap | 继承Dictionary(已过时) |
迭代器 | fail-fast迭代器 | 较老的枚举器 |
扩容机制 | 2倍扩容 | 2倍+1扩容 |
推荐使用 | 单线程环境首选 | 基本被ConcurrentHashMap取代 |
Q:为什么Hashtable不允许null而HashMap允许?
A:主要因为:
- Hashtable的线程安全设计使null值语义模糊(无法区分"不存在"和"值为null")
- Hashtable的contains()方法与null值存在歧义
- HashMap作为后来设计,更注重实用性和灵活性
Q:如何使HashMap线程安全?
A:三种方式:
- 使用Collections.synchronizedMap()包装
- 使用ConcurrentHashMap
- 手动加锁(不推荐)
Q:HashMap和Hashtable的hash计算有什么区别?
A:
- HashMap使用键的hashCode()并经过扰动函数处理:
(h = key.hashCode()) ^ (h >>> 16)
- Hashtable直接使用键的hashCode():
hash = key.hashCode(); index = (hash & 0x7FFFFFFF) % table.length;
HashMap作为更现代的实现,在大多数场景下都是更好的选择,而Hashtable已成为遗留类,新代码中应优先考虑ConcurrentHashMap。
HashMap的哈希计算方法详解
HashMap计算哈希值的过程是其高效性的核心所在,主要包含两个关键步骤:基础哈希计算和扰动函数处理。
一、完整哈希计算流程
1. JDK 8中的哈希计算方法
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
2. 计算步骤分解
- 处理null键:
如果key为null,直接返回0
(key == null) ? 0 : ...
- 获取基础哈希值:
调用key对象的hashCode()方法
h = key.hashCode()
- 扰动处理:
将哈希值右移16位后与原值进行异或操作
h ^ (h >>> 16)
二、设计原理分析
为什么要使用扰动函数?
问题 | 解决方案 | 效果 |
哈希碰撞 | 高位参与运算 | 使低位更随机 |
数组长度有限 | 混合高低位 | 充分利用哈希值信息 |
哈希质量差 | 二次扰动 | 弥补劣质hashCode()实现 |
三、索引定位实现
计算最终桶位置的完整过程:
// n是table的长度(总是2的幂)
int index = (n - 1) & hash;
为什么用(n-1) & hash?
用位运算代替模运算
方法 | 等价形式 | 优点 |
hash % n | 取模运算 | 通用但慢 |
(n-1) & hash | 按位与运算 | 速度快,要求n是2的幂 |
猜你喜欢
- 2025-04-24 Java面试题专集--HashMap
- 2025-04-24 mycat分库分表
- 2025-04-24 UP主分销系统平台化升级与演进
- 2025-04-24 HashMap实现原理一步一步分析(1-put方法源码整体过程)
- 2025-04-24 全网讲解最透彻:HashMap&ConcurrentHashMap总结 等你来看
- 2025-04-24 面试:说一下HashMap的底层实现原理,我懵了
- 2025-04-24 腾讯二面:1G内存如何对40亿QQ号去重?#腾讯二面
- 2025-04-24 面试官 : 你能说清楚 Redis 哈希槽和一致性哈希的要点吗?
- 2025-04-24 HashMap 底层源码分析
- 2025-04-24 Java常用类库与技巧
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)