HashMap与HashTable异同学习笔记

本文对比分析了HashMap与HashTable的异同,包括它们的继承关系、线程安全性、contains方法、对null值的支持、遍历方式、hash值计算以及扩容策略。HashMap非线程安全,适合单线程环境;HashTable线程安全,但效率较低。此外,HashMap在某些情况下可能存在无效扩容,而ConcurrentHashMap则提供了更高效率的线程安全解决方案。
摘要由CSDN通过智能技术生成

HashTable

底层数组+链表实现

无论key还是value都不能为null

线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低

初始size为11,扩容:newsize = oldsize * 2 + 1

计算index的方法:index = (hash & 0xFFFFFFF)% tab.length

HashMap

底层数组+链表实现

Key和value可以为null

线程不安全

初始size为16,扩容:newsize = oldsize * 2,size一定为2的n次幂

扩容是针对整个Map,每次扩容时,原来数组中的元素一次重新计算存放位置,并重新插入

插入元素后才判断该不该扩容,有可能无效扩容

当Map中元素总数超过Entry数组的75%,触发扩容操作,为了减少链表长度,元素分配更均匀

ConcurrentHashMap

底层采用分段的数组+链表实现

线程安全

通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍

Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术

扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容

HashTable和HashMap同:

都是用hash算法来决定其元素的存储,因此HashMao和Hashtable的hash表包含如下属性:

容量(capacity):hash表中桶的数量

初始化容量(initial capacity):创建hash表时桶的数量,HashMap允许在构造中指定初始化容量

尺寸(size):当前hash表中记录的数量

负载因子(load factor):负载因子等于size/capacity,0的时候表示空的hash表,0.5则表示半满的hash表,以此类推,另外,hash表中还存在一个“负载极限”,当hash表中的负载因子达到指定的负载极限时,hash表就会自动成倍的增加容量,并将原有的对象重新分配,其默认值为0.75

HashTable和HashMap异:

1.继承的父类不同:

HashTable继承Dictionary类,而HashMap继承AbstractMap类。但二者都是先了Map接口

2.线程安全性不同:

Javadoc中关于hashmap的一段描述如下:此实现不是同步的。如果多个线程同时访问一个哈希映射,而其中至少一个线程从结构上修改了该映射,则它必须保持外部同步

Hashtable中的方法是Synchronize的,而HashMap中的方法在缺省情况下是非Synchronize的。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步,但使用HashMap时就必须要自己增加同步处理,这一般通过对自然封装该映射的对象进行同步操作,如果不存在这样的对象,则应该使用Collection.synchronizedMap方法来“包装”该映射。最好在创建时完成这一操作,以防止对映射进行意外的非同步访问

3.contain方法的区别

HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey,因为contains方法容易让人引起误解

Hashtable则保留了contains,containsValue和containsKey三个方法,其中contains和containsValue功能相同

4.key和value是否允许null值

Hashtable中,key和value都不允许出现null值,但是如果在Hashtable中有类似(null,null)的操作,编译没有问题,运行时则会抛出异常

5.遍历方式内部实现

Hashtable,HashMap的遍历都使用了迭代器Iterator,然而Hashtable还使用了Enumeration的方式。

6.hash值不同

哈希值的使用不同,HashTable直接适用对象的hashCode。而HashMap重新计算hash值

HashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值

7.内部实现使用的数组初始化和扩容方式不同

HashTable在不指定容量的情况下默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。

Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的两倍

 

参考博客:https://www.cnblogs.com/heyonggang/p/9112731.html

                  https://www.cnblogs.com/williamjie/p/9099141.html

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值