1

阿里巴巴建议这样遍历Map,今天就用几种方式做个比较一下看那种最好用 - 程序员xiaozh...

 1 year ago
source link: https://www.cnblogs.com/scott1102/p/17300721.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

阿里巴巴建议这样遍历Map,今天就用几种方式做个比较一下看那种最好用

​今天不举例子了,问一句你开心吗?不开心也要记得把开心的事情放到快乐源泉小瓶子里,偶尔拿出来一一遍历看看。

Map在我们Java程序员高频使用的一种数据结构,Map的遍历方式也有很多种,那那种方式比较高效呢,今天就带大家一起验证下。

先说一下阿里巴巴Java开发手册的建议:

【推荐】使用entrySet遍历Map类集合K/V,而不是用keySet方式遍历。 

说明:keySet其实遍历了2次,一次是转换为Iterator对象,另一次是从hashMap种取出key对应的value。如果是JDK8,使用Map.forEash方法。

1:通过for和map.entrySet()方式遍历。

// Map初始化
 private  static Map<String,Integer> initMap(int count){
        AlternativeJdkIdGenerator alternativeJdkIdGenerator = new AlternativeJdkIdGenerator();
        Map<String,Integer> map = new HashMap<>();
        for (int i = 0; i < count; i++) {
            map.put(alternativeJdkIdGenerator.generateId().toString(),i) ;
        }
        return  map ;
    }
int count = 1000000;
        Map<String,Integer> map =initMap(count) ;
        // 为了计算平均值,分别循环三次进行遍历
        for (int i = 0; i < 3; i++) {
            Instant start;
            Instant end;
            start = Instant.now();
            for (Map.Entry<String, Integer> entry : map.entrySet()) {
                // 一般遍历map就是获取key和value
                String  result="key为:"+entry.getKey()+",value为:"+entry.getValue();
            }
            end = Instant.now();
            System.out.println("遍历循环" + count + "次耗时:" + Duration.between(start, end).toMillis() + "ms");
        }

运行三次的结果如下:(平均值:368.33ms)

2591839-20230409175356322-65863491.png

​2、通过 for, Iterator 和 map.entrySet() 来遍历

  int count = 1000000;
        Map<String,Integer> map =initMap(count) ;
        for (int i = 0; i < 3; i++) {
            Instant start;
            Instant end;
            start = Instant.now();
            for (Iterator<Map.Entry<String,Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) {
                Map.Entry<String,Integer> entry = entries.next();
                String result ="key为:"+entry.getKey()+",value为:"+entry.getValue();
            }
            end = Instant.now();
            System.out.println("遍历循环" + count + "次耗时:" + Duration.between(start, end).toMillis() + "ms");
        }

​运行三次的结果如下:(平均值:339.66ms)

2591839-20230409175520108-1875715775.png

 ​3、通过 for 和 map.keySet() 来遍历

 int count = 1000000;
        Map<String,Integer> map =initMap(count) ;
        for (int i = 0; i < 3; i++) {
            Instant start;
            Instant end;
            start = Instant.now();
            for (String key : map.keySet()) {
                String result ="key为:"+key+",value为:"+map.get(key);
            }
            end = Instant.now();
            System.out.println("遍历循环" + count + "次耗时:" + Duration.between(start, end).toMillis() + "ms");
        }

运行三次的结果如下:(平均值:379.66ms)

2591839-20230409175645666-144683646.png

​4、通过 for,Iterator 和 map.keySet() 来遍历

  int count = 1000000;
        Map<String,Integer> map =initMap(count) ;
        for (int i = 0; i < 3; i++) {
            Instant start;
            Instant end;
            start = Instant.now();
            for (Iterator<String> key = map.keySet().iterator(); key.hasNext(); ) {
                String k = key.next();
                String result ="key为:"+k+",value为:"+map.get(k);
            }
            end = Instant.now();
            System.out.println("遍历循环" + count + "次耗时:" + Duration.between(start, end).toMillis() + "ms");
        }

运行三次的结果如下:(平均值330.33ms)

2591839-20230409175830110-172368179.png

 5、通过 map.forEach() 来遍历

int count = 1000000;
        Map<String,Integer> map =initMap(count) ;
        for (int i = 0; i < 3; i++) {
            Instant start;
            Instant end;
            start = Instant.now();
            map.forEach((key, value) -> {
                String result ="key为:"+key+",value为:"+map.get(value);
            });
            end = Instant.now();
            System.out.println("遍历循环" + count + "次耗时:" + Duration.between(start, end).toMillis() + "ms");
        }

​运行三次的结果如下:(平均值506.33ms)

2591839-20230409175947744-540814711.png

​经过上面的验证(在大批量数据的时候,数据量小的时候没测试,感觉数据量小的化耗时太小更不好比较)最好不要用map.forEach()来遍历Map。在普通的遍历方法中 entrySet() 的方法要比使用 keySet() 的方法好。【PS虽然keySet() 的平均值有时候比较小,但它的波动性比较大,所以还是考虑阿里巴巴Java开发手册的建议使用entrySet()遍历Map】。

看过 HashMap 源码的同学应该会发现,这个遍历方式【entrySet(】在源码中也有使用,如下图所示。

 
2591839-20230409180040262-635508086.png

 ​Spring的源码也有很多的Map,大神们遍历的方式也都基本使用entrySet()遍历如下:

2591839-20230409180115616-610014717.png

 所以开发中也建议使用entrySet()来遍历Map。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK