HashMap 与 Hashtable

相同点

  • 均实现了Map、Cloneable、Serializable三个接口,均可以被序列化或克隆。
  • 负载因子默认均为 0.75
  • 二者的存储结构相同,解决冲突的方法略有不同

不同点

  • 实现方式不同

    • HashMap 继承自 AbstractMap 抽象类

    • Hashtable 继承自 Directory 抽象类

      • jdk 1.2 开始,Map接口被引入,它提供了更好的键值对映射实现,Dictionary抽象类也被废弃了。

      • Dictionary类只允许键和值的类型为Object,而Map接口支持泛型,可以指定键和值的类型。

      • Dictionary类的方法命名与Map接口也有所不同,Dictionary类中的方法命名较为复杂,而Map接口中的方法命名更加简洁明了。

  • 线程安全方面

    • HashMap是非线程安全的,只适用于单线程环境下,多线程环境下可以采用concurrent并发包下的ConcurrentHashMap
    • Hashtable是线程安全的,能用于多线程环境中。

    ConcurrentHashMapHashtable都是线程安全的。在早期版本中,Hashtable比较常用,但是在目前的 Java 版本中, ConcurrentHashMap 更为常用,原因如下:

    • 同步机制差异
      Hashtable 使用了 synchronized 关键字来保证线程安全,即在每个公共方法上都进行了同步锁定。而 ConcurrentHashMap 则使用了分离锁技术来实现并发访问,它将哈希表分成多个段(Segment),每个段都拥有自己的锁,不同的线程可以同时访问不同的段,从而提高了并发性能。

    • 迭代器支持不同
      由于 ConcurrentHashMap 使用了分离锁技术,因此不能保证在迭代时对所有的元素都能获取到正确的结果,可能会遗漏一些元素。而 Hashtable 则没有这个问题,遍历时可以保证获取到所有的元素。

      由于在遍历时不会对整个哈希表进行加锁,因此在遍历期间,有可能会有其他线程对哈希表进行修改,导致遍历时漏掉一些元素或者重复访问一些元素,从而导致遍历结果不准确。为了解决这个问题,ConcurrentHashMap提供了一些迭代器的变种,如KeySetView、EntrySetView和Values等,可以保证遍历时不会遗漏任何元素。

    • 同步性能差异

      Hashtable中的所有方法都是同步的,而ConcurrentHashMap仅在需要同步的时候进行同步,所以 ConcurrentHashMap 的性能更高。

    • 功能差异

      ConcurrentHashMapHashtable更加丰富,例如支持 keySet()values()entrySet() 等方法。

    • 可扩展性差异

      Hashtable不支持扩展(自动扩容),而ConcurrentHashMap可以根据需要自动扩展。

  • 数据结构方面

    • jdk1.8 开始,HashMap加入了红黑树

    • Hashtable则一直为链表

  • Hashtable 是不允许键或值为 null 的,HashMap 的键值则都可以为 null。

  • hash值算法不同

    • HashMap添加元素时,使用hash()方法,增加hashCode的随机性

    • Hashtable添加元素时,是直接采用key的hashCode()

  • 索引算法不同

    • Hashtable 在计算索引时,用 % 运算

    • HashMap 在计算索引时,则用 & 运算(数组长度为2的幂次方,而且位运算更高效)

  • 初始化容量不同

    • HashMap 的初始容量为:16,要求数组容量一定为2的整数次幂

    • Hashtable 初始容量为:11,不要求数组容量一定为2的整数次幂

    两者的负载因子默认都是:0.75。

  • 扩容机制不同

    当 已用容量 > 总容量 * 负载因子 时

    • HashMap 扩容规则为当前容量翻倍
    • Hashtable 扩容规则为当前容量翻倍 +1
  • 迭代器不同

    • HashMap 使用 Iterator 迭代器(支持 fail-fast 机制)

      fail-fast 机制

      • 如果在迭代过程中,被遍历的集合被修改了(比如添加或删除元素),就会抛出一个ConcurrentModificationException异常,从而提供一种迭代器与集合同步的机制。

      • 这种机制是通过迭代器(Iterator)来实现的,迭代器中维护了一个操作计数器(modCount),每当集合结构发生改变时,计数器的值会增加。在迭代器遍历集合时,如果发现计数器的值与开始遍历时不一致,就会抛出ConcurrentModificationException异常,以保证集合的一致性和避免并发修改问题。

      • 如果使用 Iterator.remove() 方法删除元素时,该方法本身会更新 modCount 的值,因此不会出现计数器不一致的情况(单线程环境下,若多线程环境,则可能抛出ConcurrentModificationException异常)。

    • Hashtable 支持 Iterator 和 Enumeration 两种

      enumerator迭代器是一个旧的Java集合框架中的迭代器接口,已经被新的Iterator接口所取代。在JDK 1.0和1.1中,Java集合框架只提供了enumerator接口来进行集合的迭代操作。在Java 2中,新增了Iterator接口来替换enumerator接口,Iterator接口提供了更强大和灵活的迭代功能,并且支持 fail-fast 机制。

  • 部分API不同

    • HashMap不支持contains(Object value)方法,没有重写toString()方法

    • HashTable支持contains(Object value)方法,而且重写了toString()方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值