HashMap的遍历方式及其性能分析

HashMap遍历

HashMap 遍历从大的方向来说,可分为以下 4 类

  1. 迭代器(Iterator)方式遍历;

  2. For Each 方式遍历;

  3. Lambda 表达式遍历(JDK 1.8以后);

  4. Streams API 遍历(JDK 1.8以后)。

但每种类型下又有不同的实现方式,因此具体的遍历方式又可以分为以下 7 种:

  1. 使用迭代器EntrySet 的方式进行遍历;

  2. 使用迭代器KeySet 的方式进行遍历;

  3. 使用 For Each EntrySet 的方式进行遍历;

  4. 使用 For Each KeySet 的方式进行遍历;

  5. 使用 Lambda 表达式的方式进行遍历;

  6. 使用 Streams API 单线程的方式进行遍历;

  7. 使用 Streams API 多线程的方式进行遍历;

性能分析

1. Streams API 多线程 > 迭代器EntrySet ≈ For Each EntrySet > Streams API 单线程 > 迭代器KeySet ≈ For Each KeySet

2.  entrySet 的性能比 keySet 的性能高出了一倍左右,因此我们应该尽量使用 entrySet  来实现 Map 集合的遍历。

3. 通过迭代器循环和 for 循环的遍历的 EntrySet 或者KeySet最终生成的字节码是一样的,因此其性能大致相同

为什么EntrySet比 KeySet 的性能高一倍?

   KeySet在使用迭代器或者 for 循环时,已经遍历了一遍 Map 集合了,再用 map.get(key) 查询时,相当于遍历了两遍集合。而 EntrySet 只遍历了一遍 Map 集合,之后把 key 和 value 值都放入到了 Entry 对象中,因此再获取 key 和 value 值时就无需再遍历 Map 集合。所以EntrySet 的性能比 KeySet 的性能高出了一倍,因为 KeySet 相当于循环了两遍 Map 集合,而 EntrySet 只循环了一遍。

迭代遍历过程为什么不能直接使用map.remove()删除元素?

        我们不能在遍历中使用集合 map.remove() 来删除数据,这是非安全的操作方式,但我们可以使用迭代器的 iterator.remove() 的方法来删除数据,是安全的删除集合的方式。

        在使用HashMap进行遍历和删除操作时,不能在遍历过程中直接删除元素,这是因为HashMap的迭代器设计不支持在遍历时对集合进行结构性修改。当在遍历过程中直接删除元素时,会导致迭代器的状态与实际集合的状态不一致,可能引发ConcurrentModificationException(并发修改异常)。

        具体来说,当创建HashMap的迭代器时,会生成一个"modCount"字段,表示HashMap结构性修改的次数。每当对HashMap进行插入、删除等操作时,"modCount"都会增加。而在迭代器遍历HashMap时,会将当前的"modCount"与之前保存的"expectedModCount"进行比较,如果两者不相等,则会抛出ConcurrentModificationException。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值