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

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


当前回答

如果要按元素添加的顺序遍历映射,请使用LinkedHashMap,而不是仅使用map。

这种方法在过去对我很有效:

LinkedHashMap<String,Integer> test=new LinkedHashMap();

test.put("foo",69);
test.put("bar",1337);

for(int i=0;i<test.size();i++){
    System.out.println(test.get(test.keySet().toArray()[i]));
}

输出:

69
1337

其他回答

使用Java 7

Map<String,String> sampleMap = new HashMap<>();
for (sampleMap.Entry<String,String> entry : sampleMap.entrySet()) {
    String key = entry.getKey();
    String value = entry.getValue();

    /* your Code as per the Business Justification  */

}

使用Java 8

Map<String,String> sampleMap = new HashMap<>();

sampleMap.forEach((k, v) -> System.out.println("Key is :  " + k + " Value is :  " + v));

Java 8:

可以使用lambda表达式:

myMap.entrySet().stream().forEach((entry) -> {
    Object currentKey = entry.getKey();
    Object currentValue = entry.getValue();
});

有关详细信息,请遵循以下步骤。

在地图上迭代的典型代码是:

Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
    String key = entry.getKey();
    Thing thing = entry.getValue();
    ...
}

HashMap是规范映射实现,不做任何保证(或者,如果不对其执行任何变异操作,则不应更改顺序)。SortedMap将根据键的自然顺序或Comparator(如果提供)返回条目。LinkedHashMap将按照插入顺序或访问顺序返回条目,具体取决于它的构造方式。EnumMap以键的自然顺序返回条目。

(更新:我认为这不再是真的。)注意,IdentityHashMap entrySet迭代器目前有一个特殊的实现,它为entrySet中的每个项返回相同的Map.Entry实例!然而,每次新迭代器推进Map.Entry时都会更新。

每个地图

简单地使用Map::forEach,其中键和值都传递给BiConsumer怎么样?

map.forEach((k,v)->{
    System.out.println(k+"->"+v);
});

为了总结其他答案并将它们与我所知道的结合起来,我找到了10种主要的方法(见下文)。此外,我还编写了一些性能测试(见下面的结果)。例如,如果我们想找到映射的所有键和值的总和,我们可以写:

使用迭代器和Map.Entry长i=0;迭代器<Map.Entry<Integer,Integer>>it=Map.entrySet().iiterator();while(it.hasNext()){Map.Entry<Integer,Integer>pair=it.next();i+=pair.getKey()+pair.getValue();}使用foreach和Map.Entry长i=0;for(Map.Entry<Integer,Integer>对:Map.entrySet()){i+=pair.getKey()+pair.getValue();}使用Java 8中的forEach最终长[]i={0};map.forEach((k,v)->i[0]+=k+v);使用keySet和foreach长i=0;for(整数键:map.keySet()){i+=键+map.get(键);}使用keySet和迭代器长i=0;Iterator<Integer>itr2=map.keySet().Iterator();而(itr2.hasNext()){整数键=itr2.next();i+=键+map.get(键);}使用for和Map.Entry长i=0;for(Iterator<Map.Entry<Integer,Integer>>条目=Map.entrySet().Iterator();entries.hasNext();){Map.Entry<Integer,Integer>Entry=entries.next();i+=entry.getKey()+entry.getValue();}使用Java 8流API最终长[]i={0};map.entrySet().stream().forEach(e->i[0]+=e.getKey()+e.getValue());并行使用Java 8流API最终长[]i={0};map.entrySet().stream().allel().forEach(e->i[0]+=e.getKey()+e.getValue());使用Apache集合的IterableMap长i=0;MapIterator<Integer,Integer>it=iterableMap.MapIterator();while(it.hasNext()){i+=it.next()+it.getValue();}使用Eclipse(CS)集合的MutableMap最终长[]i={0};mutableMap.forEachKeyValue((key,value)->{i[0]+=键+值;});

性能测试(模式=平均时间,系统=Windows 8.1 64位,Intel i7-4790 3.60 GHz,16 GB)

对于小地图(100个元素),得分0.308是最好的基准模式控制分数误差单位测试3_UsingForEachAndJava8平均值10 0.308±0.021µs/op测试10_UsingEclipseMap平均值10 0.309±0.009µs/optest1_UsingWhileAndMapEntry平均值10 0.380±0.014µs/optest6_SingingForAndIterator平均值10 0.387±0.016µs/optest2_UsingForEachAndMapEntry平均值10 0.391±0.023µs/op测试7_UsingJava8StreamApi平均值10 0.510±0.014µs/optest9_UsingApacheIterableMap平均值10 0.524±0.008µs/optest4_UsingKeySetAndForEach平均值10 0.816±0.026µs/optest5_UsingKeySetAndIterator平均值10 0.863±0.025µs/optest8_UsingJava8StreamApiParallel平均值10 5.552±0.185µs/op对于包含10000个元素的地图,得分37.606是最好的基准模式控制分数误差单位测试10_UsingEclipseMap平均值10 37.606±0.790µs/op测试3_使用EachAndJava8平均值10 50.368±0.887µs/op测试6_SingingForAndIterator平均值10 50.332±0.507µs/optest2_UsingForEachAndMapEntry平均值10 51.406±1.032µs/op测试1_UsingWhileAndMapEntry平均值10 52.538±2.431µs/op测试7_UsingJava8StreamApi平均值10 54.464±0.712µs/optest4_UsingKeySetAndForEach平均值10 79.016±25.345µs/optest5_UsingKeySetAndIterator平均值10 91.105±10.220µs/optest8_UsingJava8StreamApiParallel平均值10 112.511±0.365µs/optest9_UsingApacheIterableMap平均值10 125.714±1.935µs/op对于包含100000个元素的地图,得分1184.767是最好的基准模式控制分数误差单位测试1_UsingWhileAndMapEntry平均值10 1184.767±332.968µs/op测试10_UsingEclipseMap平均值10 1191.735±304.273µs/optest2_UsingForEachAndMapEntry平均值10 1205.815±366.043µs/op测试6_SingingForAndIterator平均值10 1206.873±367.272µs/optest8_UsingJava8StreamApiParallel平均值10 1485.895±233.143µs/optest5_UsingKeySetAndIterator平均值10 1540.281±357.497µs/optest4_UsingKeySetAndForEach平均值10 1593.342±294.417µs/op测试3_UsingForEachAndJava8平均值10 1666.296±126.443µs/op测试7_UsingJava8StreamApi平均值10 1706.676±436.867µs/optest9_UsingApacheIterableMap平均值10 3289.866±1445.564µs/op

图表(性能测试取决于地图大小)

表(性能测试取决于地图大小)

          100     600      1100     1600     2100
test10    0.333    1.631    2.752    5.937    8.024
test3     0.309    1.971    4.147    8.147   10.473
test6     0.372    2.190    4.470    8.322   10.531
test1     0.405    2.237    4.616    8.645   10.707
test2     0.376    2.267    4.809    8.403   10.910
test7     0.473    2.448    5.668    9.790   12.125
test9     0.565    2.830    5.952   13.220   16.965
test4     0.808    5.012    8.813   13.939   17.407
test5     0.810    5.104    8.533   14.064   17.422
test8     5.173   12.499   17.351   24.671   30.403

所有测试都在GitHub上。