Hashmap七种实现方式在性能安全上的对比

Hashmap七种实现方式在性能安全上的对比

七种实现方式及分类

在这里插入图片描述

因为创建的方式一样 所以所有的创建hashmap只做一次

    // 创建并赋值 HashMap
        Map<Integer, String> map = new HashMap();
        map.put(1, "Java");
        map.put(2, "JDK");
        map.put(3, "Spring Framework");
        map.put(4, "MyBatis framework");
        map.put(5, "Java中文社群");	

1 迭代器Entryset

    // 遍历
        Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, String> entry = iterator.next();
            System.out.print(entry.getKey());
            System.out.print(entry.getValue());
        }

2迭代器keyset

  for (Map.Entry<Integer, String> entry : map.entrySet()) {
            System.out.print(entry.getKey());
            System.out.print(entry.getValue());
        }

3ForEach EntrySet

  // 遍历
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            System.out.print(entry.getKey());
            System.out.print(entry.getValue());
        }

4ForEach KeySet

   // 遍历
        for (Integer key : map.keySet()) {
            System.out.print(key);
            System.out.print(map.get(key));
        }

5Lambda

   // 遍历
        map.forEach((key, value) -> {
            System.out.print(key);
            System.out.print(value);
        });

Streams API 单线程

  // 遍历
        map.entrySet().stream().forEach((entry) -> {
            System.out.print(entry.getKey());
            System.out.print(entry.getValue());
        });

Streams API 多线程

     // 遍历
        map.entrySet().parallelStream().forEach((entry) -> {
            System.out.print(entry.getKey());
            System.out.print(entry.getValue());
        });
类型结果
1迭代器 EntrySet1 Java 2 JDK 3 Spring Framework 4 MyBatis framework 5 Java中文社群
2迭代器 KeySet1 Java 2 JDK 3 Spring Framework 4 MyBatis framework 5 Java中文社群
3ForEach EntrySet1 Java 2 JDK 3 Spring Framework 4 MyBatis framework 5 Java中文社群
4.ForEach KeySet1 Java 2 JDK 3 Spring Framework 4 MyBatis framework 5 Java中文社群
5Lambda1 Java 2 JDK 3 Spring Framework 4 MyBatis framework 5 Java中文社群
6Streams API 单线程1 Java 2 JDK 3 Spring Framework 4 MyBatis framework 5 Java中文社群
7Streams API 多线程4 MyBatis framework 5 Java中文社群 1 Java 2 JDK 3 Spring Framework

性能测试:

经过oracle官方提供的性能测试jmh测试得出的实验结果为:

图片

其中 Score 列表示平均执行时间, ± 符号表示误差。从以上结果可以看出,如果加上后面的误差值的话,可以得出的结论是,除了并行循环的 parallelStream 性能比极高之外(多线程方式性能肯定比较高),其他方式的遍历方法在性能方面几乎没有任何差别。

解析原因

解析所有 遍历代码(通过javac编译成字节码)

package com.example;

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

public class HashMapTest {
    static Map<Integer, String> map = new HashMap() {
        {
            for(int var1 = 0; var1 < 2; ++var1) {
                this.put(var1, "val:" + var1);
            }

        }
    };

    public HashMapTest() {
    }

    public static void main(String[] var0) {
        entrySet();
        keySet();
        forEachEntrySet();
        forEachKeySet();
        lambda();
        streamApi();
        parallelStreamApi();
    }

    public static void entrySet() {
        Iterator var0 = map.entrySet().iterator();

        while(var0.hasNext()) {
            Entry var1 = (Entry)var0.next();
            System.out.println(var1.getKey());
            System.out.println((String)var1.getValue());
        }

    }

    public static void keySet() {
        Iterator var0 = map.keySet().iterator();

        while(var0.hasNext()) {
            Integer var1 = (Integer)var0.next();
            System.out.println(var1);
            System.out.println((String)map.get(var1));
        }

    }

    public static void forEachEntrySet() {
        Iterator var0 = map.entrySet().iterator();

        while(var0.hasNext()) {
            Entry var1 = (Entry)var0.next();
            System.out.println(var1.getKey());
            System.out.println((String)var1.getValue());
        }

    }

    public static void forEachKeySet() {
        Iterator var0 = map.keySet().iterator();

        while(var0.hasNext()) {
            Integer var1 = (Integer)var0.next();
            System.out.println(var1);
            System.out.println((String)map.get(var1));
        }

    }

    public static void lambda() {
        map.forEach((var0, var1) -> {
            System.out.println(var0);
            System.out.println(var1);
        });
    }

    public static void streamApi() {
        map.entrySet().stream().forEach((var0) -> {
            System.out.println(var0.getKey());
            System.out.println((String)var0.getValue());
        });
    }

    public static void parallelStreamApi() {
        map.entrySet().parallelStream().forEach((var0) -> {
            System.out.println(var0.getKey());
            System.out.println((String)var0.getValue());
        });
    }
}

从结果可以看出,除了lambda和streams api,其他的遍历方式最终生成的方式都是在循环中遍历一个entry,因此其实性能都差不多,但是更推荐entryset(更优雅)

安全测试:

1,迭代器方式

Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<Integer, String> entry = iterator.next();
    if (entry.getKey() == 1) {
        // 删除
        System.out.println("del:" + entry.getKey());
        iterator.remove();
    } else {
        System.out.println("show:" + entry.getKey());
    }
}
结果:安全

show:0

del:1

show:2

2.for循环方式

for (Map.Entry<Integer, String> entry : map.entrySet()) {
    if (entry.getKey() == 1) {
        // 删除
        System.out.println("del:" + entry.getKey());
        map.remove(entry.getKey());
    } else {
        System.out.println("show:" + entry.getKey());
    }
}
结果:不安全

图片

3.Lambda 方式

map.forEach((key, value) -> {
    if (key == 1) {
        System.out.println("del:" + key);
        map.remove(key);
    } else {
        System.out.println("show:" + key);
    }
});  //错误方法
// 根据 map 中的 key 去判断删除
map.keySet().removeIf(key -> key == 1);
map.forEach((key, value) -> {
    System.out.println("show:" + key);
});//正确方法
结果:可以先使用 LambdaremoveIf 删除多余的数据,再进行循环是一种正确操作集合的方式。

4.Stream 方式

方式1:
map.entrySet().stream().forEach((entry) -> {
    if (entry.getKey() == 1) {
        System.out.println("del:" + entry.getKey());
        map.remove(entry.getKey());
    } else {
        System.out.println("show:" + entry.getKey());
    }
});
结果:不安全

图片

方式2:
map.entrySet().stream().filter(m -> 1 != m.getKey()).forEach((entry) -> {
    if (entry.getKey() == 1) {
        System.out.println("del:" + entry.getKey());
    } else {
        System.out.println("show:" + entry.getKey());
    }
});
结果:安全

show:0

show:2

可以使用 Stream 中的 filter 过滤掉无用的数据,再进行遍历也是一种安全的操作集合的方式。

总结:

性能方面

:除了Stream的并行循环其他的都差不多

简洁性选择

Lambda 和 Stream

安全性:

  System.out.println("del:" + entry.getKey());
} else {
    System.out.println("show:" + entry.getKey());
}

});
``

######结果:安全

show:0

show:2

可以使用 Stream 中的 filter 过滤掉无用的数据,再进行遍历也是一种安全的操作集合的方式。

总结:

性能方面

:除了Stream的并行循环其他的都差不多

简洁性选择

Lambda 和 Stream

安全性:

使用迭代器提供的 iterator.remove() 方法来进行删除,这种方式是安全的在遍历中删除集合的方式,或者使用 Stream 中的 filter 过滤掉要删除的数据再进行循环,也是安全的操作方式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值