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

元素的顺序是否取决于我对接口的特定映射实现?


当前回答

如果您有一个通用的非类型映射,可以使用:

Map map = new HashMap();
for (Map.Entry entry : ((Set<Map.Entry>) map.entrySet())) {
    System.out.println(entry.getKey() + "/" + entry.getValue());
}

其他回答

是的,顺序取决于特定的Map实现。

@ScArcher2具有更优雅的Java 1.5语法。在1.4中,我会这样做:

Iterator entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Entry thisEntry = (Entry) entries.next();
  Object key = thisEntry.getKey();
  Object value = thisEntry.getValue();
  // ...
}

对于Eclipse集合,您将在MapIterable接口上使用forEachKeyValue方法,该方法由MutableMap和ImmutableMap接口及其实现继承。

MutableMap<Integer, String> map = 
    Maps.mutable.of(1, "One", 2, "Two", 3, "Three");

MutableBag<String> result = Bags.mutable.empty();
map.forEachKeyValue((key, value) -> result.add(key + value));

MutableBag<String> expected = Bags.mutable.of("1One", "2Two", "3Three");
Assertions.assertEquals(expected, result);

将forEachKeyValue与EclipseCollections(EC)Map实现一起使用比使用entrySet更有效的原因是因为EC Map实现不存储Map.Entry对象。将entrySet与EC Map实现一起使用会动态生成Map.Entry对象。forEachKeyValue方法能够避免创建Map.Entry对象,因为它可以直接导航Map实现的内部结构。在这种情况下,使用内部迭代器比使用外部迭代器有好处。

注意:我是Eclipse集合的提交人。

如果您通过Map进行迭代的原因是对值执行操作并写入结果Map。我建议在GoogleGuavaMaps类中使用转换方法。

import com.google.common.collect.Maps;

将地图添加到导入后,可以在地图上使用Maps.transformValues和Maps.transform Entries,如下所示:

public void transformMap(){
    Map<String, Integer> map = new HashMap<>();
    map.put("a", 2);
    map.put("b", 4);

    Map<String, Integer> result = Maps.transformValues(map, num -> num * 2);
    result.forEach((key, val) -> print(key, Integer.toString(val)));
    // key=a,value=4
    // key=b,value=8

    Map<String, String> result2 = Maps.transformEntries(map, (key, value) -> value + "[" + key + "]");
    result2.forEach(this::print);
    // key=a,value=2[a]
    // key=b,value=4[b]
}

private void print(String key, String val){
    System.out.println("key=" + key + ",value=" + val);
}

仅供参考,如果您只对映射的键/值感兴趣,而对其他键/值不感兴趣,那么也可以使用map.keySet()和map.values()。

使用迭代器和泛型的示例:

Iterator<Map.Entry<String, String>> entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Map.Entry<String, String> entry = entries.next();
  String key = entry.getKey();
  String value = entry.getValue();
  // ...
}