• 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的?
  • 相关阅读:
    k8s网络策略
    二进制部署Kubernetes
    宿主机的命令在容器中使用
    高可用示例
    企业级高可用Harbor 2.3
    openstack常用shell脚本
    shell实现jumpserver
    我曾七次鄙视自己的灵魂
    queue容器适配器模拟超市结账环节
    stack容器适配器实现计算器(含实现代码)
  • 原文地址:https://www.cnblogs.com/summerday152/p/13626130.html
Copyright © 2020-2023  润新知