Java 中HashMap 的几种遍历方式以及遍历速度

使用 keySet() 遍历键

for (K key : map.keySet()) {
    V value = map.get(key);
}
  • 优点:简单直观。
  • 缺点:在每次循环时调用 map.get(key),这意味着对于每个键都会执行一次哈希查找,性能稍差。

使用 entrySet() 遍历键值对(Iterator的方式)

for (Map.Entry<K, V> entry : map.entrySet()) {
    K key = entry.getKey();
    V value = entry.getValue();
}
  • 优点:效率较高。因为 entrySet() 直接返回 Map.Entry,同时获取键和值,不需要再次调用 get()。
  • 缺点:无显著缺点。

使用 forEach 方法(Java 8 及之后)

map.forEach((key, value) -> {
    // 操作键和值
});
  • 优点:简洁且高效,利用内部优化。
  • 缺点:可读性可能对部分开发者不如传统遍历方式。

使用 Stream API 遍历

map.entrySet().stream().forEach(entry -> {
    K key = entry.getKey();
    V value = entry.getValue();
});

优点:

  • List item
    • 可以利用并行流(parallelStream())进行并行处理,适合大规模数据处理。
    • 语法简洁优雅,符合函数式编程风格。
  • 缺点:
    • 在小规模数据或简单场景下,Stream 的开销可能稍大,尤其是在引入并行流时,可能增加线程管理开销。
    • 相比于直接的 for-each 循环,在某些场景下 Stream 可能会稍慢,因为它会引入额外的中间操作步骤。

性能

如果考虑到普通数据规模和常见遍历场景,性能通常是以下顺序:

  1. entrySet()(传统遍历,键值同时获取)
  2. forEach()(简洁且性能接近 entrySet())
  3. Stream(在并行流中可能更快,普通场景下稍慢)
  4. keySet()(需要额外的 get() 操作)

Stream 更适合大规模并行处理场景,而在小规模数据或常规使用场景下,entrySet()方式通常是最快的选择。

以下是通过代码进行对比的结果

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class HashMapIteration {

    private static final int ITERATIONS = 100000;  // 遍历的次数
    private static final int MAP_SIZE = 10000;     // HashMap 中的元素数量

    public static void main(String[] args) {
        // 初始化 HashMap
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < MAP_SIZE; i++) {
            map.put(i, i);
        }

        // 测试 keySet + get() 的时间
        long startTime = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            for (Integer key : map.keySet()) {
                Integer value = map.get(key);
            }
        }
        long endTime = System.nanoTime();
        System.out.println("Method 1 (keySet + get) Time: " + (endTime - startTime) / 1000000 + " ms");

        // 测试 entrySet 的时间
        startTime = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
                Integer key = entry.getKey();
                Integer value = entry.getValue();
            }
        }
        endTime = System.nanoTime();
        System.out.println("Method 2 (entrySet) Time: " + (endTime - startTime) / 1000000 + " ms");

        // 测试 forEach 的时间
        startTime = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            map.forEach((key, value) -> {
                // 遍历键值对
            });
        }
        endTime = System.nanoTime();
        System.out.println("Method 3 (forEach) Time: " + (endTime - startTime) / 1000000 + " ms");

        // 测试 Stream API 的时间
        startTime = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            map.entrySet().stream().forEach(entry -> {
                Integer key = entry.getKey();
                Integer value = entry.getValue();
            });
        }
        endTime = System.nanoTime();
        System.out.println("Method 4 (Stream) Time: " + (endTime - startTime) / 1000000 + " ms");

        // 测试使用 Iterator 的时间
        startTime = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            Iterator<Map.Entry<Integer, Integer>> iterator = map.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Integer, Integer> entry = iterator.next();
                Integer key = entry.getKey();
                Integer value = entry.getValue();
            }
        }
        endTime = System.nanoTime();
        System.out.println("Method 5 (Iterator) Time: " + (endTime - startTime) / 1000000 + " ms");

    }
}

Method 1 (keySet + get) Time: 6883 ms
Method 2 (entrySet) Time: 4670 ms
Method 3 (forEach) Time: 2699 ms
Method 4 (Stream) Time: 4199 ms
Method 5 (Iterator) Time: 4609 ms


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值