专业的JAVA编程教程与资源

网站首页 > java教程 正文

HashMap和HashTable的区别

temp10 2025-04-24 08:24:12 java教程 10 ℃ 0 评论


核心区别总结

特性

HashMap和HashTable的区别

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:主要因为:

  1. Hashtable的线程安全设计使null值语义模糊(无法区分"不存在"和"值为null")
  2. Hashtable的contains()方法与null值存在歧义
  3. HashMap作为后来设计,更注重实用性和灵活性

Q:如何使HashMap线程安全?
A:三种方式:

  1. 使用Collections.synchronizedMap()包装
  2. 使用ConcurrentHashMap
  3. 手动加锁(不推荐)

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. 计算步骤分解

  1. 处理null键

如果key为null,直接返回0

(key == null) ? 0 : ...
  1. 获取基础哈希值

调用key对象的hashCode()方法

h = key.hashCode()
  1. 扰动处理

将哈希值右移16位后与原值进行异或操作

h ^ (h >>> 16)

二、设计原理分析

为什么要使用扰动函数?

问题

解决方案

效果

哈希碰撞

高位参与运算

使低位更随机

数组长度有限

混合高低位

充分利用哈希值信息

哈希质量差

二次扰动

弥补劣质hashCode()实现

三、索引定位实现

计算最终桶位置的完整过程:

// n是table的长度(总是2的幂)
int index = (n - 1) & hash;

为什么用(n-1) & hash?

用位运算代替模运算

方法

等价形式

优点

hash % n

取模运算

通用但慢

(n-1) & hash

按位与运算

速度快,要求n是2的幂



Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表