集合框架——HashTable和HashMap的区别[通俗易懂]

集合框架——HashTable和HashMap的区别[通俗易懂]继承类不同HashTable继承Dictionary类,HashMap继承AbstractMap类线程安全级别不同HashTable是线程安全的类,每个public方法都有Synchronized修饰,HashMap不是线程安全的是否允许null的要求不同HashTable:key不允许为null,value不允许为nullHashMap:key允许为null,value允许为n…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

  • 继承类不同

HashTable继承Dictionary类,HashMap继承AbstractMap类

  • 线程安全级别不同

HashTable是线程安全的类,每个public方法都有Synchronized修饰,HashMap不是线程安全的

  • 是否允许null的要求不同

HashTable:key不允许为null,value不允许为null

HashMap:key允许为null,value允许为null

  • 底层数据结构不同

在JDK1.8以后,HashMap的底层数据结构改成了数组+链表+红黑树的实现,在链表的节点大于TREEIFY_THRESHOLD=8时,链表转为红黑树,在树节点小于UNTREEIFY_THRESHOLD=6时,红黑树转变为链表。(之所以有8和6两个阈值是为了避免某个链表在临界点频繁插入删除,导致转换频繁降低性能)

而Hashtable的底层实现就是数组+链表,而没有红黑树,因此各种操作都要简单很多。

  • 容量的要求不同

Hashtable的容量是直接使用用户输入的容量initialCapacity。

HashMap在用户输入的基础上,强制将容量转换为大于输入容量的最小2的幂次方数值,通过tableSizeFor(int cap)函数实现。

  • index的计算方法不同

HashTbale是古老的除留余数法,直接使用hashcode

int hash = key.hashCode();  
int index = (hash & 0x7FFFFFFF) % tab.length; 

而HashMap是强制容量为2的幂,重新根据hashcode计算hash值,在使用hash & (length-1),也等价取膜,但更加高效,取得的位置更加分散,偶数,奇数保证了都会分散到,HashTbale就不能保证

static int indexFor(int h, int length) {  
  return h & (length-1);  
  • 扩容方法不同

HashTable扩容后新容量是原容量的2倍+1,新threshold为新容量*loadFactor。然后在oldMap中对数组从尾部开始遍历,对每个链表从头部开始遍历取出节点,重新计算节点在newMap中的hashCode,放进newMap中,并把oldMap中的节点指向null。

HashMap扩容后新容量是原容量的2倍,新threshold为2倍旧threshold。在扩容时,由于是2倍扩容,可以得到新的index要么不变,要么是旧index+oldCapacity。并且是从链表(红黑树)头部开始遍历,并将节点分别顺序放到高、低两个链表中,然后将链表头部链接到数组的相应bucket中。

基于上述不同,因此hashMap的扩容效率更高,并且JDK1.8后也不会出现resize()导致的线程不安全。

  • 方法不同

HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey,因为contains方法容易让人引起误解。而Hashtable有contains方法、containsvalue方法和containsKey方法,其中contains方法和containsvalue方法是一样的。

  • 迭代器不同

HashMap的迭代器(Iterator)是fail-fast迭代器,所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。

而Hashtable除了有Iterator迭代器还有enumerator迭代器,并且enumerator迭代器不是fail-fast的。

*关于fail-fast机制:fail-fast是通过modcount参数实现的,在HashMap中每当有会修改HashMap结构的操作被执行,那么modcount加1,modcount是volatile的,因此是线程可见的,在迭代过程中,判断modCount跟expectedModCount是否相等,如果不相等就表示已经有其他线程修改了Map。而HashTable并没有这个参数,因此没有fail-fast机制。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/192210.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Databus Relays

    Databus Relays概述DatabusRelays主要负责以下两个工作:从databus源数据库中读取变化行,并序列化为事件流保存至内存中;接受客户端的请求,并将数据变化事件流返回给客户端。技术架构 EventProducer:用来读取数据库的变化事件,转化为AVRO类型并存储至内存中;CircularBuffer:Relay有一个或多个环形的缓冲池用来保存按递增

    2022年10月16日
  • Java–反射机制原理、几种Class获取方式及应用场景[通俗易懂]

    Java–反射机制原理、几种Class获取方式及应用场景[通俗易懂]目录学习背景一、Java反射机制是什么?1.1反射原理1.2举例说明二、Java反射机制中获取Class的三种方式及区别?2.1三种方式及区别2.2代码演示区别三、Java反射机制的应用场景有哪些?3.1应用场景3.2应用场景实现3.2.1简单工厂模式3.2.2简单工厂模式优化(应用场景)3.2.1代理模式中动态代理(应用场景)学习背景学习Java的小伙伴,可能听过Java反射机制,但是熟悉又有点陌生,本文主要是通过思考面试中经常被问到的几个Java反射机制的问题,再通过理论知识结合代

  • 静态路由命令配置_配置静态路由的命令格式为

    静态路由命令配置_配置静态路由的命令格式为前话之前发表了相关路由协议简单配置命令,RIP、OSPF等都是动态路由协议。这次我简单写一下静态理由简单配置命令,的确很简单一行命令就可以了。静态路由介绍静态路由是指由用户或网络管理员手工配

  • Java核心技术之什么是泛型

    Java核心技术之什么是泛型没看过官网,不知道类型擦除会产生的问题还敢说自己了解泛型?

  • sublime text3 激活码 2021【2021最新】[通俗易懂]

    (sublime text3 激活码 2021)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

  • 孙鑫的java_孙鑫java视频教程「建议收藏」

    孙鑫的java_孙鑫java视频教程「建议收藏」近几年来,提到java相信很多人都不陌生了吧,Java技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网。也正是由于互联网的快速发展,学习java的人也是越来越多了。需要注意的是,java和我们平时学习的其它计算机语言还是有区别的。Java不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号