HashMap和HashTable的理解与区别

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

大家好,又见面了,我是你们的朋友全栈君。

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

1、父类不同:

     HashMap是继承自AbstractMap类,而HashTable是继承自Dictionary(已被废弃,详情看源代码)。不过它们都实现了同时实现了map、Cloneable(可复制)、Serializable(可序列化)这三个接口。

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

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

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

2、null值问题

Hashtable既不支持Null key也不支持Null value。Hashtable的put()方法的注释中有说明 。

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

3、线程安全性

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

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

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

tip:HashMap是JDk1.2之后有的,而在JDK1.5中,伟大的Doug Lea给我们带来了concurrent包,从此Map也有安全的了。也就就是有了ConcurrentHashMap(关于这个的理解下次有机会再写,或自行百度)

4、遍历方式不同

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

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

JDK8之前的版本中,Hashtable是没有fast-fail机制的。在JDK8及以后的版本中 ,Hashtable也是使用fast-fail的。(此处可以去看一下1.5和1.8JDK源码的对比)

5、初始容量不同

Hashtable的初始长度是11,之后每次扩充容量变为之前的2n+1(n为上一次的长度)

而HashMap的初始长度为16,之后每次扩充变为原来的两倍

创建时,如果给定了容量初始值,那么Hashtable会直接使用你给定的大小,而HashMap会将其扩充为2的幂次方大小。

6、计算哈希值的方法不同

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

Hashtable直接使用对象的hashCode。hashCode是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值。然后再使用除留余数发来获得最终的位置。 然而除法运算是非常耗费时间的。效率很低

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

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

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

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

相关推荐

  • js中如何判断数组中包含某个特定的值_js数组是否包含某个值

    js中如何判断数组中包含某个特定的值_js数组是否包含某个值array.indexOf判断数组中是否存在某个值,如果存在返回数组元素的下标,否则返回-1letarr=[‘something’,’anything’,’nothing’,’anything’];letindex=arr.indexOf(‘nothing’);#结果:2array.includes(searchElement[,fromIndex])判断一个数组是否包含一个指定的值,如果存在返回true,否则返回false。参数:search..

    2022年8月31日
  • 注册公司事宜(注册公司需要什么条件)

    本公司专主代办广州注册公司,广州公司注册,创业者可选择的注册公司主要有两类:一是在海外注册公司,二是在内地如广州注册公司,。不管在国内注册还是在海外基本的操作模式都是相同的,只不过对于成立的公司在手续、税收等政策上有点不同,但就是这点不同,会对未来的公司造成巨大的影响。一、在海外注册公司与广州注册公司的区别      创办企业者可以选择在海外注册公司,现在流行的注册海外公司的方法是注册离岸公司。

    2022年4月11日
  • C# .net中获取台式电脑中串口设备的名称

    C# .net中获取台式电脑中串口设备的名称

    2022年2月23日
  • leetcode-14最长公共前缀(分治|二分)[通俗易懂]

    leetcode-14最长公共前缀(分治|二分)[通俗易懂]原题链接编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。示例 1:输入:strs = [“flower”,”flow”,”flight”]输出:”fl”示例 2:输入:strs = [“dog”,”racecar”,”car”]输出:””解释:输入不存在公共前缀。 提示:0 <= strs.length <= 2000 <= strs[i].length <= 200strs[i] 仅由小写英文字母组成题解分

    2022年8月9日
  • C++实现字符串分割函数split()「建议收藏」

    C++实现字符串分割函数split()「建议收藏」目录使用strtok()完成分割使用strsep()完成分割使用strtok_r()完成分割实现字符串分割前言最近遇到了一个字符串分割的问题,在C++的标准库里面没有字符分割函数split()。我想这个问题今后可能还会再遇见,所以使用C/C++中的字符串分割方法完成相应的功能。需求:对一个字符串进行分割,然后将分割后的数据存起来,想用的时候像用数组那样拿就行了。所以在完…

    2022年6月3日
  • 语义分割 实例分割 全景分割_语义分割应用场景

    语义分割 实例分割 全景分割_语义分割应用场景之前看过一篇使用分割思想进行目标检测,所以这里补习下一些分割相关的基础知识。这里重点说下语义分割、实力分割和全景分割的区别。1、semanticsegmentation(语义分割)通常意义上的目标分割指的就是语义分割,图像语义分割,简而言之就是对一张图片上的所有像素点进行分类语义分割(下图左)就是需要区分到图中每一点像素点,而不仅仅是矩形框框住了。但是同一物体的不同实例不需要单独分…

    2022年8月21日

发表回复

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

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