HashMap的各种遍历和删除方式总结

前言

  • 介绍HashMap遍历的几种方式
  • 介绍HashMap迭代删除的几种方式

HashMap遍历的几种方式

一、迭代器遍历

迭代EntrySet

    @Test
    public void testEntrySet() {
        Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            System.out.println(entry.getKey() + " --> " + entry.getValue());
        }
    }

迭代KeySet

    @Test
    public void testKeySet() {
        Iterator<String> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            System.out.println(key + " --> " + map.get(key));
        }
    }

二、ForEach遍历

遍历EntrySet

    @Test
    public void testForEachEntrySet() {
        for (Map.Entry<String, String> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " --> " + entry.getValue());
        }
    }

遍历KeySet

    @Test
    public void testForEachKeySet() {
        for (String key : map.keySet()) {
            System.out.println(key + " --> " + map.get(key));
        }
    }

三、Lambda遍历

    @Test
    public void testLambda() {
        map.forEach((key, value) -> {
            System.out.println(key + " --> " + value);
        });
    }

四、StreamAPI遍历

    @Test
    public void testStream() {
        map.entrySet().stream().forEach(entry -> {
            System.out.println(entry.getKey() + " --> " + entry.getValue());
        });
    }
    @Test
    public void testParallelStream() {
        map.entrySet().parallelStream().forEach(entry -> {
            System.out.println(entry.getKey() + " --> " + entry.getValue());
        });
    }

各种遍历方式的性能比较

引入jmh性能测试框架

    <dependencies>
        <dependency>
            <groupId>org.openjdk.jmh</groupId>
            <artifactId>jmh-core</artifactId>
            <version>1.23</version>
        </dependency>
        <dependency>
            <groupId>org.openjdk.jmh</groupId>
            <artifactId>jmh-generator-annprocess</artifactId>
            <version>1.20</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

编写测试

@BenchmarkMode(Mode.Throughput) //测试类型 吞吐量
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) //预热2轮,每次1秒
@Measurement(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS) //测试5轮,每次3s
@Fork(1)  //fork 1个线程
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread) //每个测试线程1个实例
public class HashMapBenchmark {
    static Map<String, String> map = new HashMap<String,String>() {
        {
            put("author", "天乔巴夏");
            put("title", "HashMap的各种遍历方式");
            put("url", "www.hyhwky.com");
        }
    };

    public static void main(String[] args) throws RunnerException {
        System.out.println(System.getProperties());
        Options opt = new OptionsBuilder()
                .include(HashMapBenchmark.class.getSimpleName())
                .output(System.getProperty("user.dir") + "\\HashMapBenchmark.log")
                .build();
        new Runner(opt).run();
    }

    @Benchmark
    public void testEntrySet() {
        Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            System.out.println(entry.getKey() + " --> " + entry.getValue());
        }
    }

    @Benchmark
    public void testKeySet() {
        Iterator<String> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            System.out.println(key + " --> " + map.get(key));
        }
    }

    @Benchmark
    public void testForEachEntrySet() {
        for (Map.Entry<String, String> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " --> " + entry.getValue());
        }
    }

    @Benchmark
    public void testForEachKeySet() {
        for (String key : map.keySet()) {
            System.out.println(key + " --> " + map.get(key));
        }
    }

    @Benchmark
    public void testLambda() {
        map.forEach((key, value) -> {
            System.out.println(key + " --> " + value);
        });
    }

    @Benchmark
    public void testStream(){
        map.entrySet().stream().forEach(entry ->{
            System.out.println(entry.getKey() + " --> " + entry.getValue());
        });
    }

    @Benchmark
    public void testParallelStream(){
        map.entrySet().parallelStream().forEach(entry ->{
            System.out.println(entry.getKey() + " --> " + entry.getValue());
        });
    }
}

测试结果如下

Benchmark                              Mode  Cnt  Score   Error   Units
HashMapBenchmark.testEntrySet         thrpt    5  6.929 ± 1.042  ops/ms
HashMapBenchmark.testForEachEntrySet  thrpt    5  7.025 ± 0.627  ops/ms
HashMapBenchmark.testForEachKeySet    thrpt    5  7.024 ± 0.481  ops/ms
HashMapBenchmark.testKeySet           thrpt    5  6.769 ± 1.231  ops/ms
HashMapBenchmark.testLambda           thrpt    5  7.056 ± 0.300  ops/ms
HashMapBenchmark.testParallelStream   thrpt    5  5.784 ± 0.216  ops/ms
HashMapBenchmark.testStream           thrpt    5  6.826 ± 0.578  ops/ms
  • Score表示平均执行时间,Error表示误差。
  • 测试结果和本机性能有一定关系,只需关注相对结果即可。
  • 可以看出除了Parallel的遍历方法,其他方法在性能上的差别不大。

HashMap迭代删除的几种方式

迭代器删除

    @Test
    public void testRemoveIterator() {
        Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next().getKey();
            if ("title".equals(key)) {
                iterator.remove();
            }
        }
        System.out.println(map);
    }

Lambda的removeIf

    @Test
    public void testRemoveLambda() {
        map.keySet().removeIf("title"::equals);
        System.out.println(map);
    }

StreamAPI的filter

    @Test
    public void testRemoveStream() {
        map.entrySet()
                .stream()
                .filter(m -> !"title".equals(m.getKey()))
                .forEach(entry -> {
                    System.out.println(entry.getKey() + " --> " + entry.getValue());
                });
    }

参考文章

  • Java中文社群:你一般是怎么遍历HashMap的?
posted @ 2020-09-07 12:18  天乔巴夏丶  阅读(2027)  评论(0编辑  收藏  举报