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();
}
使用 foreach 和 Map.Entry
long i = 0;
for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
i += pair.getKey() + pair.getValue();
}
使用Java 8中的 forEach
final long[] i = {0};
map.forEach((k, v) -> i[0] += k + v);
使用 keySet 和 foreach
long i = 0;
for (Integer key : map.keySet()) {
i += key + map.get(key);
}
使用 keySet 和 iterator
long i = 0;
Iterator<Integer> itr2 = map.keySet().iterator();
while (itr2.hasNext()) {
Integer key = itr2.next();
i += key + map.get(key);
}
使用 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();
}
使用Java 8 Stream API
final long[] i = {0};
map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
使用Java 8 Stream API parallel
final long[] i = {0};
map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
使用 IterableMap 的 Apache Collections
long i = 0;
MapIterator<Integer, Integer> it = iterableMap.mapIterator();
while (it.hasNext()) {
i += it.next() + it.getValue();
}
使用Eclipse(CS)集合的 MutableMap
final long[] i = {0};
mutableMap.forEachKeyValue((key, value) -> {
i[0] += key + value;
});
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.
(Update: I think this is no longer true. )注意, IdentityHashMapentrySet iterator目前有一个特殊的实现,它为 entrySet 中的每个项返回相同的 Map.Entry 实例!但是,每次新的迭代器前进时,_79002都会更新 .
30 回答
Java 8:
您可以使用lambda表达式:
有关更多信息,请按照this .
如果您有一个通用的无类型 Map ,您可以使用:
是的,订单取决于具体的Map实施 .
@ScArcher2 has the more elegant Java 1.5 syntax . 在1.4中,我会做这样的事情:
最紧凑的Java 8:
如果您通过
Map
进行迭代的原因是对值进行操作并写入结果Map
. 我建议在Google GuavaMaps
类中使用transform
-methods .将
Maps
添加到导入后,可以在 Map 上使用Maps.transformValues
和Maps.transformEntries
,如下所示:在Map中,一个可以迭代
keys
和/或values
和/或both (e.g., entrySet)
取决于一个人的兴趣_喜欢:1.)迭代 Map 的keys -> keySet():
2.)迭代 Map 的values -> values():
3.)迭代 Map 的both -> entrySet():
此外,通过HashMap迭代有3种不同的方法 . 它们如下_
使用Java 8:
为了总结其他答案并将它们与我所知道的结合起来,我找到了10种主要方法(见下文) . 另外,我写了一些性能测试(见下面的结果) . 例如,如果我们想要找到 Map 的所有键和值的总和,我们可以写:
Apache Collections
Perfomance tests (mode = AverageTime,system = Windows 8.1 64-bit,Intel i7-4790 3.60 GHz,16 GB)
图表(性能测试取决于 Map 大小)
表(性能测试取决于 Map 大小)
所有测试都在GitHub上 .
随着 Java 8
使用迭代器和泛型的示例:
从理论上讲,最有效的方法取决于Map的实现 . 执行此操作的官方方法是调用
map.entrySet()
,它返回一组Map.Entry
,每个包含一个键和一个值(entry.getKey()
和entry.getValue()
) .在特殊实现中,无论您使用
map.keySet()
,map.entrySet()
还是其他内容,都可能会有所不同 . 但我想不出有人会这样写的原因 . 很可能它对你的表现没有任何影响 .是的,订单将取决于实施 - 以及(可能)插入顺序和其他难以控制的因素 .
[编辑]我原本写了
valueSet()
但当然entrySet()
实际上是答案 .Java 8
我们有
forEach
方法接受lambda expression . 我们还有stream API . 考虑一张 Map :Iterate over keys:
Iterate over values:
Iterate over entries (Using forEach and Streams):
流的优点是它们可以在我们想要的情况下轻松并行化 . 我们只需要使用
parallelStream()
代替上面的stream()
.forEachOrdered vs forEach with streams ?
forEach
不遵循遭遇顺序(如果已定义),并且本质上是非确定性的,就像forEachOrdered一样 . 所以forEach不保证订单会被保留 . 另请查看this了解更多信息 .尝试使用Java 1.4:
使用Eclipse Collections(以前为GS Collections),您将在MapIterable接口上使用forEachKeyValue方法,该方法由MutableMap和ImmutableMap接口及其实现继承 .
使用Java 8 lambda语法,您可以按如下方式编写代码:
Note: 我是Eclipse Collections的提交者 .
是的,因为很多人都认为这是迭代
Map
的最好方法 .但如果 Map 是
null
,则有机会抛出nullpointerexception
. 别忘了把null
.check放入 .这是一个两部分问题:
如何迭代Map的条目 - @ ScArcher2完美地具有answered .
迭代的顺序是什么 - 如果你只是使用
Map
,那么严格来说,有 no ordering guarantees . 所以你不应该真正依赖任何实现给出的顺序 . 但是,SortedMap接口扩展Map
并提供您正在寻找的内容 - 实现将提供一致的排序顺序 .NavigableMap is another useful extension - 这是一个
SortedMap
,其他方法可以通过键集中的有序位置查找条目 . 因此,这可能会消除首先迭代的需要 - 您可能能够在使用higherEntry
,lowerEntry
,ceilingEntry
或floorEntry
方法后找到特定的entry
.descendingMap
方法甚至为您提供 reversing the traversal order 的显式方法 .在Java 1.8(Java 8)中,通过使用来自 Iterable 接口的迭代器的聚合操作( Stream operations )中的 forEach 方法,这变得更加容易 .
只需将下面的语句粘贴到您的代码中,然后将 HashMap 变量从 hm 重命名为您的HashMap变量,以打印出键值对 .
下面是我尝试使用 Lambda Expression 的示例代码 . 这东西很酷 . 一定要试 .
也可以使用 Spliterator .
UPDATE
包括Oracle Docs的文档链接 . 有关 Lambda 的详细信息,请转至link,必须阅读Aggregate Operations,对于Spliterator,请转至link .
正确的方法是使用接受的答案,因为它是最有效的 . 我发现以下代码看起来更清晰 .
要么
有很多方法可以做到这一点 . 以下是几个简单的步骤:
假设您有一个 Map ,如:
然后你可以做类似下面的事情迭代 Map 元素 .
迭代 Map 有几种方法 .
这里是通过在 Map 中存储一百万个键值对来比较它们在 Map 中存储的公共数据集的性能,并将迭代在 Map 上 .
1) Using entrySet() in for each loop
50毫秒
2) Using keySet() in for each loop
76毫秒
3) Using entrySet() and iterator
50毫秒
4) Using keySet() and iterator
75毫秒
我已经提到this link .
仅供参考,如果您只对 Map 的键/值感兴趣而不是对另一个感兴趣,您也可以使用
map.keySet()
和map.values()
.在Java 8中,您可以使用新的lambdas功能清洁和快速地执行此操作:
k
和v
的类型将由编译器推断,不再需要使用Map.Entry
.十分简单!
迭代 Map 的典型代码是:
HashMap
是规范 Map 实现,并不保证(或者如果不对其执行变异操作则不应更改顺序) .SortedMap
将根据键的自然顺序返回条目,或Comparator
(如果提供) .LinkedHashMap
将以插入顺序或访问顺序返回条目,具体取决于它的构造方式 .EnumMap
按键的自然顺序返回条目 .(Update: I think this is no longer true. )注意,
IdentityHashMap
entrySet
iterator目前有一个特殊的实现,它为entrySet
中的每个项返回相同的Map.Entry
实例!但是,每次新的迭代器前进时,_79002都会更新 .排序将始终取决于具体的 Map 实施 . 使用Java 8,您可以使用以下任一方法:
要么:
结果将是相同的(相同的顺序) . 由映射支持的entrySet,以便您获得相同的顺序 . 第二个是方便的,因为它允许你使用lambda,例如如果您只想打印大于5的Integer对象:
下面的代码显示了LinkedHashMap和普通HashMap的迭代(示例) . 你会看到顺序的不同:
你可以使用泛型来做到这一点: