Java HashMap和Hashtable的原理和区别

本文详细对比了Java中HashMap与Hashtable的原理与区别,包括数据结构、存取元素方式及线程安全性等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、概述:HashMap 基于哈希表<key,value>,实现Map接口,接受null的键和值,不允许重复的key,但允许重复的value,即不同的key可以对应相同的value值,非线程安全,Hashtable和HashMap非常类似,同样实现了Map接口,但是Hashtable不接受null的键和值,Hashtable是线程安全的,Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

2、数据结构:数组和链表的结合。本身是一个数组,数组中的元素是链表。如图所示:

数组中存储的是链表的头结点,元素存储到数组中的规则是:一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。

HashMap和Hashtable里面有一个静态内部类Entry,其重要属性包括key,value,next,从这些属性就可以看出这是对键值对实现的一个基础bean,所以HashMap和Hashtable是一个线性数组Entry[]

3、存数据

键值对A,通过计算key的hash值得到index,则该元素存储在Entry[index],当有键值对B获得的index相同时,上面我们提到过Entry类里面有一个next属性,作用是指向下一个Entry,所以HashMap会这样做:B.next = A,Entry[index] = B,如果又进来C,index也相同,那么C.next = B,Entry[index] = C,数组中存储的是最后插入的元素(注:HashMap和Hashtable里面设置一个加载因子,随着map的size越来越大,Entry[]会根据加载因子以一定的规则加长长度。)

4、取元素,先根据key值获取到键值对在数组中的下标,然后再遍历该下标处的链表。

5、null key总是存放在Entry[]数组的第一个元素。

6、HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。

注:“快速失败”也就是fail-fast,它是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操作时,有可能会产生fail-fast机制。记住是有可能,而不是一定。例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast机制。

posted on 2017-05-26 10:07 明耀 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/mingyao123/p/6907136.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值