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的?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM