Map四种遍历方式及性能对比


一、通过keySet进行遍历

  • 一般适用于只需要Map中key的时候使用,通过key来get对应的value值效率较低,比较耗时;
/**
 * 利用keySet进行遍历
 */
public static void showMapWithKeySet(Map<String, Integer> userMap) { // 传入一个Map类型的参数
    Long start = System.currentTimeMillis(); // 遍历前当前系统的时间
    // 遍历步骤
    // 1.通过userMap.keySet()得到传入Map中所有的key
    // 2.通过for循环遍历得到每一个key
    // 3.通过userMap.get()方法get到每个key对应的value值
    for (String key : userMap.keySet()) {
        System.out.println(key + "---" + userMap.get(key));
    }
    Long end = System.currentTimeMillis(); // 遍历后当前系统的时间
    System.out.println("iterator time = " + (end - start)); // end - start即遍历Map所花费时间
}

二、通过values进行遍历

  • 一般适用于只需要Map中value的时候使用;
/**
 * 利用values进行遍历
 */
public static void showMapWithValues(Map<String, Integer> userMap) { // 传入一个Map类型的参数
    Long start = System.currentTimeMillis(); // 遍历前当前系统的时间
    // 遍历步骤
    // 1.通过userMap.values()得到传入Map中所有的value
    // 2.通过for循环遍历得到每一个value值
    for (Integer value : userMap.values()) {
        System.out.println(value);
    }
    Long end = System.currentTimeMillis(); // 遍历后当前系统的时间
    System.out.println("iterator time = " + (end - start)); // end - start即遍历Map所花费时间
}

三、通过entrySet进行遍历

  • 大多数情况下用的最多的也是最常见的,一般在键值对都需要使用,entrySet比keySet遍历的效率高很多;
/**
 * 利用entrySet进行遍历
 */
public static void showMapWithEntrySet(Map<String, Integer> userMap) {
    // 遍历步骤
    // 1.通过userMap.entrySet()得到传入Map中所有的entry (Entry将键值对的对应关系封装成了对象,即键值对。)
    // 2.通过for循环遍历得到每一个entry
    // 3.通过getKey()以及getValue()方法可以得到每个entry对应的key以及value
    for (Map.Entry<String, Integer> mapEntry : userMap.entrySet()) {
    	System.out.println(mapEntry.getKey() + "----" + mapEntry.getValue());
    }
    Long end = System.currentTimeMillis(); // 遍历后当前系统的时间
    System.out.println("iterator time = " + (end - start)); // end - start即遍历Map所花费时间
}

四、通过iterator(迭代器)进行遍历

  • iterator的遍历方式比for循环遍历效率要高;
/**
 * 利用iterator进行遍历
 */
public static void showMapWithIterator(Map<String, Integer> userMap) {
    Long start = System.currentTimeMillis(); // 遍历前当前系统的时间
    // 遍历步骤
    // 1.通过iterator()方法将得到的entry集合(或者key集合以及value集合)转换成迭代器
    // 2.判断迭代器是否有下一个元素,如果不为空,就通过next()得到entry
    // 3.通过getKey()和getValue()方法进行key和value的输出
    Iterator<Map.Entry<String, Integer>> it = userMap.entrySet().iterator();
    while (it.hasNext()) {
        it.next();
        Map.Entry<String, Integer> entry = it.next();
        System.out.println(entry.getKey() + "===" + entry.getValue());
    }
    Long end = System.currentTimeMillis(); // 遍历后当前系统的时间
    System.out.println("iterator time = " + (end - start)); // end - start即遍历Map所花费时间
}

五、性能对比(HashMap)

  • 在实验的时候保证每个遍历的方法实验环境相当,我们在每个for循环里面执行一次赋值操作以保证实验环境;
  • 在这里我执行五次程序以提高实验的准确性
// 数据输入函数
// 通过随机数让实验数据变的复杂贴近真实实验环境,这里我们向HashMap里插入一千万条数据
// 测试遍历一千万条数据每种遍历方式所需的时间
public static Map inputMap() {
    Map<String, Integer> userMap = new HashMap<String, Integer>(500000, 0.75f);
    String str[] = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"};
    String key;
    Integer value;
    for (int i = 0; i <= 10000000; i++) {
        int m = (int)(Math.random() * 10);
        key = String.valueOf(str[m] + i * 100);
        value = i;
        userMap.put(key, value);
    }
    return userMap;
}
// 程序主函数
public static void main(String[] args) {
    Map map1 = inputMap();
    showMap1(map1);
    showMap2(map1);
    showMap3(map1);
    showMap4(map1);
}
  • 各种遍历方式所花费时间对比表格(使用HashMap时):
遍历Map的次数 keySet Time(ms) values time(ms) entrySet time(ms) iterator time(m's)
第一次 686 443 470 413
第二次 697 453 461 401
第三次 645 415 447 425
第四次 664 452 471 400
第五次 632 415 455 387
  1. 得出结论:结果显而易见,四种遍历方式中,在绝大多数的情况下使用iterator方式效率最高,而使用keySet去遍历效率最低;
  2. 当然这里iterator方式我们使用entrySet方法并转换为迭代器,使用keySet和values方法可能得到不同给的结果,大家有兴趣可以自己去尝试;
  3. 但是如果只需要得到key值时,keySet遍历方法也许比entrySet更为合适,因为entrySet将value也给取出来了,浪费了空间;大家可以自己测一下在只需要得到key值时keySet和entrySet方式各自的耗时时长;
  4. 同理,只需要value值时,values遍历方法是最优选择,entrySet会略好于keySet方法;
  5. 感兴趣可以测一下values和keySet转换为迭代器遍历各自所耗费的时长;
  • 作者:周海林(联系作者)
  • 发表时间:2099-04-12
  • 版权声明:自由转载-非商用-非衍生-周海林贼帅
  • 加作者微信:请在文末添加作者微信

评论