1.1 如何有效地遍历Java Map中的每个条目?| Java Debug 笔记

788 阅读1分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看<活动链接>

提问:如何有效地遍历Java Map中的每个条目?

如果我有一个用Java实现Map接口的对象,并且希望对其中包含的每一对(key,value)进行迭代,那么遍历该map实例的最有效方法是什么?

元素的顺序是否取决于我对接口的特定映射实现(即hash方法)?

总结回答:

  1. 使用迭代器和Map.Entry
long i = 0;
Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry<Integer, Integer> pair = it.next();
    i += pair.getKey() + pair.getValue();
}
  1. 使用foreach和Map.Entry
Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + "/" + entry.getValue());
}
  1. 使用Java 8新特性Lambda表达式以及forEach
final long[] i = {0};
map.forEach((k, v) -> i[0] += k + v);
  1. 用keySet代替Map.Entry
  2. 使用for和Map.Entry
long i = 0;
for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) {
    Map.Entry<Integer, Integer> entry = entries.next();
    i += entry.getKey() + entry.getValue();
}
  1. 使用Java 8 Stream API
final long[] i = {0};
map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
  1. 使用Apache Collections的IterableMap
long i = 0;
MapIterator<Integer, Integer> it = iterableMap.mapIterator();
while (it.hasNext()) {
    i += it.next() + it.getValue();
}

上述方法总结了如何遍历,接下来回答map遍历顺序与什么有关

例子代码如下

public static void main(String[] args) {
        HashMap<Integer, Integer> hp = new HashMap<>();
        hp.put(1,1);
        hp.put(3,3);
        hp.put(0,0);
        hp.put(2,2);
       // long i = 0;
        Iterator<Map.Entry<Integer, Integer>> it = hp.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Integer, Integer> pair = it.next();
            System.out.println(pair.getKey() + " : " + pair.getValue());
           //i += pair.getKey() + pair.getValue();
        }

    }

输出有:

0 : 0
1 : 1
2 : 2
3 : 3

得出结论,map遍历顺序与插入顺序无关。

至于遍历顺序是什么,严格来说,是没有顺序的,因为我们并不是所有的map都是Integer为key。(不过可以保证每次遍历的顺序是一样的)