hashmap和hashtable和hashset的区别_反映和反应的区别

hashmap和hashtable和hashset的区别_反映和反应的区别HashMap与Hashtable的区别是面试中经常遇到的一个问题。这个问题看似简单,但如果深究进去,也能了解到不少知识。本文对两者从来源,特性,算法等多个方面进行对比总结。力争多角度,全方位的展示二者的不同,做到此问题的终结版。作者Hashtable的作者:HashMap的作者:HashMap的作者比Hashtable的作者多了著名顶顶的并发大神DougLea。他写了util…

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

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

HashMap与Hashtable的区别是面试中经常遇到的一个问题。这个问题看似简单,但如果深究进去,也能了解到不少知识。本文对两者从来源,特性,算法等多个方面进行对比总结。力争多角度,全方位的展示二者的不同,做到此问题的终结版。

  1. 作者

Hashtable的作者:
在这里插入图片描述

HashMap的作者:
在这里插入图片描述

Hash Map的作者比Hashtable的作者多了著名顶顶的并发大神Doug Lea。他写了util.concurrent包。著有并发编程圣经Concurrent Programming in Java: Design Principles and Patterns 一书。他的个人主页:http://g.oswego.edu/

Josh Bloch 为领导了众多Java平台特性的设计和实现,其中包括Java Collection框架、java.math包以及assert机制。著有 Effective Java 一书。

Arthur van Hoff最早任职于硅谷的Sun Microsystems公司,从事Java程序语言的早期开发工作。设计并实现了JDK 1.0的许多方面,包括Java编译器、Java调试器、许多标准Java类以及HotJava浏览器。随后创立了多家成功的企业,其中包括Marimba(1999年IPO)、Strangeberry(后被TiVo收购)、ZING(后被Dell收购)和Ellerdale(后被Flipboard收购)。Java命名来源有这么一种说法,来源于开发人员名字的组合:James Gosling、Arthur Van Hoff和Andy Bechtolsheim首字母的缩写。

Neal Gafter是Java SE 4和5语言增强的主要设计者和实现者,他的Java闭包实现赢得了OpenJDK创新者挑战赛的大奖。他也在继续参与SE 7和8的语言发展。之前Neal在为Google的在线日历工作,也曾经是C++标准委员会的一员,并曾在Sun微系统公司,MicroTec研究院和德州仪器领导开发C和C++编译器。如今Neal在微软开发.NET平台编程语言。Neal是《Java Puzzlers:Traps, Pitfalls and Corner Cases》(Addison Wesley,2005)一书的合作者。他拥有罗彻斯特大学计算机科学的博士学位。

可见这些作者都是java乃至整个it领域大名鼎鼎的人物。也只有这些大师级人物才能写出HashMap这么大道至简的数据类型了。

  1. 产生时间

Hashtable是java一开始发布时就提供的键值映射的数据结构,而HashMap产生于JDK1.2。虽然Hashtable比HashMap出现的早一些,但是现在Hashtable基本上已经被弃用了。而HashMap已经成为应用最为广泛的一种数据类型了。造成这样的原因一方面是因为Hashtable是线程安全的,效率比较低。另一方面可能是因为Hashtable没有遵循驼峰命名法吧。。。

  1. 继承的父类不同

HashMap和Hashtable不仅作者不同,而且连父类也是不一样的。HashMap是继承自AbstractMap类,而HashTable是继承自Dictionary类。不过它们都实现了同时实现了map、Cloneable(可复制)、Serializable(可序列化)这三个接口

在这里插入图片描述

在这里插入图片描述

Dictionary类是一个已经被废弃的类(见其源码中的注释)。父类都被废弃,自然而然也没人用它的子类Hashtable了。

  • NOTE: This class is obsolete. New implementations should

  • implement the Map interface, rather than extending this class.

  1. 对外提供的接口不同

Hashtable比HashMap多提供了elments() 和contains() 两个方法。

elments() 方法继承自Hashtable的父类Dictionnary。elements() 方法用于返回此Hashtable中的value的枚举。

contains()方法判断该Hashtable是否包含传入的value。它的作用与containsValue()一致。事实上,contansValue() 就只是调用了一下contains() 方法。

在这里插入图片描述

  1. 对Null key 和Null value的支持不同

Hashtable既不支持Null key也不支持Null value。Hashtable的put()方法的注释中有说明。
在这里插入图片描述

当key为Null时,调用put() 方法,运行到下面这一步就会抛出空指针异常。因为拿一个Null值去调用方法了。

当value为null值时,Hashtable对其做了限制,运行到下面这步也会抛出空指针异常。
在这里插入图片描述

HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。

  1. 线程安全性不同

Hashtable是线程安全的,它的每个方法中都加入了Synchronize方法。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步

HashMap不是线程安全的,在多线程并发的环境下,可能会产生死锁等问题。具体的原因在下一篇文章中会详细进行分析。使用HashMap时就必须要自己增加同步处理,

虽然HashMap不是线程安全的,但是它的效率会比Hashtable要好很多。这样设计是合理的。在我们的日常使用当中,大部分时间是单线程操作的。HashMap把这部分操作解放出来了。当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。

  1. 遍历方式的内部实现上不同

Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。

HashMap的Iterator是fail-fast迭代器。当有其它线程改变了HashMap的结构(增加,删除,修改元素),将会抛出ConcurrentModificationException。不过,通过Iterator的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。

JDK8之前的版本中,Hashtable是没有fast-fail机制的。在JDK8及以后的版本中 ,HashTable也是使用fast-fail的, 源码如下:

在这里插入图片描述

modCount的使用类似于并发编程中的CAS(Compare and Swap)技术。我们可以看到这个方法中,每次在发生增删改的时候都会出现modCount++的动作。而modcount可以理解为是当前hashtable的状态。每发生一次操作,状态就向前走一步。设置这个状态,主要是由于hashtable等容器类在迭代时,判断数据是否过时时使用的。尽管hashtable采用了原生的同步锁来保护数据安全。但是在出现迭代数据的时候,则无法保证边迭代,边正确操作。于是使用这个值来标记状态。一旦在迭代的过程中状态发生了改变,则会快速抛出一个异常,终止迭代行为。

  1. 初始容量大小和每次扩充容量大小的不同

Hashtable默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。

创建时,如果给定了容量初始值,那么Hashtable会直接使用你给定的大小,而HashMap会将其扩充为2的幂次方大小。也就是说Hashtable会尽量使用素数、奇数。而HashMap则总是使用2的幂作为哈希表的大小。

之所以会有这样的不同,是因为Hashtable和HashMap设计时的侧重点不同。Hashtable的侧重点是哈希的结果更加均匀,使得哈希冲突减少。当哈希表的大小为素数时,简单的取模哈希的结果会更加均匀。而HashMap则更加关注hash的计算效率问题。在取模计算时,如果模数是2的幂,那么我们可以直接使用位运算来得到结果,效率要大大高于做除法。HashMap为了加快hash的速度,将哈希表的大小固定为了2的幂。当然这引入了哈希分布不均匀的问题,所以HashMap为解决这问题,又对hash算法做了一些改动。这从而导致了Hashtable和HashMap的计算hash值的方法不同

  1. 计算hash值的方法不同

为了得到元素的位置,首先需要根据元素的 KEY计算出一个hash值,然后再用这个hash值来计算得到最终的位置。

Hashtable直接使用对象的hashCode。hashCode是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值。然后再使用除留余数发来获得最终的位置。

Hashtable在计算元素的位置时需要进行一次除法运算,而除法运算是比较耗时的。

HashMap为了提高计算效率,将哈希表的大小固定为了2的幂,这样在取模预算时,不需要做除法,只需要做位运算。位运算比除法的效率要高很多。

HashMap的效率虽然提高了,但是hash冲突却也增加了。因为它得出的hash值的低位相同的概率比较高,而计算位运算

为了解决这个问题,HashMap重新根据hashcode计算hash值后,又对hash值做了一些运算来打散数据。使得取得的位置更加分散,从而减少了hash冲突。当然了,为了高效,HashMap只做了一些简单的位处理。从而不至于把使用2 的幂次方带来的效率提升给抵消掉。

在这里插入图片描述

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

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/192626.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 最简分式概念_怎样才算最简分式

    最简分式概念_怎样才算最简分式ProblemL:最简分式Description我们知道,5/3=1+3/5,称等号后面的式子为最简分式。也就是说,在分式中,分子一定要小于分母,而且分子、分母是互质的。请写一个程序,对于用户输入的一个合法分式,输出其约简之后的结果。Input输入有多行,每行是“m/n”的格式表示的一个分式,其中m和n都是int类型范围内的正整数。输入至EOF结束。Output输出的行数与输入一致,且每行输出与上述输入一一对应。如果约简后,分子部分是0,则只输出整数部分。如果整数部分是0,则按照“j/

    2025年7月3日
    2
  • 大数据平台框架、组件以及处理流程详解

    大数据平台框架、组件以及处理流程详解数据产品和数据密不可分作为数据产品经理理解数据从产生、存储到应用的整个流程,以及大数据建设需要采用的技术框架Hadoop是必备的知识清单,以此在搭建数据产品时能够从全局的视角理解从数据到产品化的价值。本篇文章从三个维度:1.大数据的处理流程2.大数据的的平台框架Hadoop3.Hadoop生态圈组件理解了数据从产生到场景应用每个环节的流程过程以及企业在建立大数据平台时需要采用的技术…

    2022年5月23日
    149
  • C# 手机号码归属地查询

    C# 手机号码归属地查询手机号码归属地的数据信息是存于某文件夹下的txt文档,打开一txt文档里面的数据格式如下:13003000000-13003009999-合肥13003010000-13003029999-蚌埠13003030000-13003049999-芜湖13003050000-13003069999-合肥13003070000-13003079999-淮南13003080000

    2022年7月22日
    19
  • 微信个人号机器人

    微信个人号机器人前段时间公司需求开发一套自定义的微信机器人,需求是可以自批量添加好友,自动聊天,自动回复,发朋友圈,转发语音,以及定时群发等,还可以提取聊天内容,进行数据汇总,what????微信还可以这样做!!调研开发了3个月,3个月啊!!!(主要被各种技术走偏路),终于成功了,都是走过的心酸泪,分享给大家,大家学习完,记得给我点个赞!!!大家一般需求点无非是以下几个需求:1.开发个人微信营销系统2.开发自定义的微信机器人,3.开发微信智能聊天客服系统4.定制行业内的群数据分析功能需求很

    2022年5月7日
    48
  • VUE父子组件之间的传值,以及兄弟组件之间的传值;

    VUE父子组件之间的传值,以及兄弟组件之间的传值;一、Vue父子组件之间传值vue使用中,经常会用到组件,好处是:1、如果有一个功能很多地方都会用到,写成一个组件就不用重复写这个功能了;2、页面内容会简洁一些;方便管控;子组件的传值是通过props来传递数据,$emit来触发事件;下面是一个简单的子组件props传值:父组件的部分:首先引入组件,在组件上绑定你要传给组件的值;然后,在组件里通过props来接收你从父页面传…

    2022年5月17日
    55
  • Win10+Ubuntu双系统修复Ubuntu系统引导

    Win10+Ubuntu双系统修复Ubuntu系统引导amp amp NBSP amp amp NBSP amp amp NBSP amp amp NBSP 这两天笔者安装 win10 ubuntu16 04 双系统 因为网络上能找到大量的资料 安装过程此处就不多讲 因为笔者电脑是华硕主板 bios 默认设置为安全启动 笔者猜测会阻止加载 ubuntu 引导 导致双系统不能随意引导 先不管那么多 现在的问题是 Ubuntu 已经安装成功 开机直接进入 win10 所以笔者的

    2025年11月23日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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