如果我有一个用Java实现Map接口的对象,并且我希望对其中包含的每一对进行迭代,那么最有效的方法是什么?
元素的顺序是否取决于我对接口的特定映射实现?
如果我有一个用Java实现Map接口的对象,并且我希望对其中包含的每一对进行迭代,那么最有效的方法是什么?
元素的顺序是否取决于我对接口的特定映射实现?
当前回答
使用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));
其他回答
Lambda表达式Java 8
在Java1.8(Java8)中,通过使用Aggregate操作(Stream操作)中的forEach方法,这变得更加容易,它看起来类似于Iterable接口中的迭代器。
只需将下面的粘贴语句复制到代码中,并将HashMap变量从hm重命名为HashMap变量,即可打印出键值对。
HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
/*
* Logic to put the Key,Value pair in your HashMap hm
*/
// Print the key value pair in one line.
hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));
// Just copy and paste above line to your code.
下面是我尝试使用Lambda表达式的示例代码。这东西太酷了。必须尝试。
HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
Random rand = new Random(47);
int i = 0;
while(i < 5) {
i++;
int key = rand.nextInt(20);
int value = rand.nextInt(50);
System.out.println("Inserting key: " + key + " Value: " + value);
Integer imap = hm.put(key, value);
if( imap == null) {
System.out.println("Inserted");
} else {
System.out.println("Replaced with " + imap);
}
}
hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));
Output:
Inserting key: 18 Value: 5
Inserted
Inserting key: 13 Value: 11
Inserted
Inserting key: 1 Value: 29
Inserted
Inserting key: 8 Value: 0
Inserted
Inserting key: 2 Value: 7
Inserted
key: 1 value:29
key: 18 value:5
key: 2 value:7
key: 8 value:0
key: 13 value:11
同样也可以使用Spliterator。
Spliterator sit = hm.entrySet().spliterator();
更新
包括指向Oracle文档的文档链接。有关Lambda的更多信息,请访问此链接,必须阅读聚合操作,对于Spliterator,请访问该链接。
为了总结其他答案并将它们与我所知道的结合起来,我找到了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上。
排序将始终取决于特定的映射实现。使用Java 8,您可以使用以下任一选项:
map.forEach((k,v) -> { System.out.println(k + ":" + v); });
Or:
map.entrySet().forEach((e) -> {
System.out.println(e.getKey() + " : " + e.getValue());
});
结果相同(顺序相同)。entrySet由地图支持,因此您可以获得相同的顺序。第二个很方便,因为它允许您使用lambdas,例如,如果您只想打印大于5的Integer对象:
map.entrySet()
.stream()
.filter(e-> e.getValue() > 5)
.forEach(System.out::println);
下面的代码显示了通过LinkedHashMap和普通HashMap的迭代(示例)。您将看到顺序的不同:
public class HMIteration {
public static void main(String[] args) {
Map<Object, Object> linkedHashMap = new LinkedHashMap<>();
Map<Object, Object> hashMap = new HashMap<>();
for (int i=10; i>=0; i--) {
linkedHashMap.put(i, i);
hashMap.put(i, i);
}
System.out.println("LinkedHashMap (1): ");
linkedHashMap.forEach((k,v) -> { System.out.print(k + " (#="+k.hashCode() + "):" + v + ", "); });
System.out.println("\nLinkedHashMap (2): ");
linkedHashMap.entrySet().forEach((e) -> {
System.out.print(e.getKey() + " : " + e.getValue() + ", ");
});
System.out.println("\n\nHashMap (1): ");
hashMap.forEach((k,v) -> { System.out.print(k + " (#:"+k.hashCode() + "):" + v + ", "); });
System.out.println("\nHashMap (2): ");
hashMap.entrySet().forEach((e) -> {
System.out.print(e.getKey() + " : " + e.getValue() + ", ");
});
}
}
输出:
LinkedHashMap (1):
10 (#=10):10, 9 (#=9):9, 8 (#=8):8, 7 (#=7):7, 6 (#=6):6, 5 (#=5):5, 4 (#=4):4, 3 (#=3):3, 2 (#=2):2, 1 (#=1):1, 0 (#=0):0,
LinkedHashMap (2):
10 : 10, 9 : 9, 8 : 8, 7 : 7, 6 : 6, 5 : 5, 4 : 4, 3 : 3, 2 : 2, 1 : 1, 0 : 0,
HashMap (1):
0 (#:0):0, 1 (#:1):1, 2 (#:2):2, 3 (#:3):3, 4 (#:4):4, 5 (#:5):5, 6 (#:6):6, 7 (#:7):7, 8 (#:8):8, 9 (#:9):9, 10 (#:10):10,
HashMap (2):
0 : 0, 1 : 1, 2 : 2, 3 : 3, 4 : 4, 5 : 5, 6 : 6, 7 : 7, 8 : 8, 9 : 9, 10 : 10,
有几种方法可以迭代地图。请参考以下代码。
使用迭代器接口迭代地图时,必须使用Entry<K,V>或entrySet()。
它看起来像这样:
import java.util.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class IteratMapDemo{
public static void main(String arg[]){
Map<String, String> mapOne = new HashMap<String, String>();
mapOne.put("1", "January");
mapOne.put("2", "February");
mapOne.put("3", "March");
mapOne.put("4", "April");
mapOne.put("5", "May");
mapOne.put("6", "June");
mapOne.put("7", "July");
mapOne.put("8", "August");
mapOne.put("9", "September");
mapOne.put("10", "Octomber");
mapOne.put("11", "November");
mapOne.put("12", "December");
Iterator it = mapOne.entrySet().iterator();
while(it.hasNext())
{
Map.Entry me = (Map.Entry) it.next();
//System.out.println("Get Key through While loop = " + me.getKey());
}
for(Map.Entry<String, String> entry:mapOne.entrySet()){
//System.out.println(entry.getKey() + "=" + entry.getValue());
}
for (Object key : mapOne.keySet()) {
System.out.println("Key: " + key.toString() + " Value: " +
mapOne.get(key));
}
}
}
有很多方法可以做到这一点。下面是几个简单的步骤:
假设您有一张地图,如:
Map<String, Integer> m = new HashMap<String, Integer>();
然后,您可以执行以下操作来迭代地图元素。
// ********** Using an iterator ****************
Iterator<Entry<String, Integer>> me = m.entrySet().iterator();
while(me.hasNext()){
Entry<String, Integer> pair = me.next();
System.out.println(pair.getKey() + ":" + pair.getValue());
}
// *********** Using foreach ************************
for(Entry<String, Integer> me : m.entrySet()){
System.out.println(me.getKey() + " : " + me.getValue());
}
// *********** Using keySet *****************************
for(String s : m.keySet()){
System.out.println(s + " : " + m.get(s));
}
// *********** Using keySet and iterator *****************
Iterator<String> me = m.keySet().iterator();
while(me.hasNext()){
String key = me.next();
System.out.println(key + " : " + m.get(key));
}