在 HashMap
中迭代项的最佳方法是什么?
如果你只对键感兴趣,你可以遍历地图的keySet()
:
Map<String, Object> map = ...;
for (String key : map.keySet()) {
// ...
}
如果你仅需要值,请使用 values()
方法。for (Object value : map.values()) {
// ...
}
如果你希望同时获取键和值,可以使用entrySet()
:
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// ...
}
一个注意事项:如果你想在迭代过程中删除元素,你需要通过 Iterator 来执行(参见 karim79 的答案)。但是,更改元素的值是可以的(参见 Map.Entry
)。
entrySet
可能更快,因为它可以避免为每个条目执行查找操作。特定Map
的实现决定了哪种方式更好,以及优势有多大。此时的GC压力也可能是一个因素。 - doug65536按以下方式遍历entrySet()
:
public static void printMap(Map mp) {
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
it.remove(); // avoids a ConcurrentModificationException
}
}
阅读有关 Map
的更多信息。
Map<Integer, Integer> map = new HashMap<Integer, Integer>(); for (Map.Entry<Integer, Integer> entry : map.entrySet()) { System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); }
- fresh_devit.remove();
这一行即可。 - Dannyfor (Map.Entry<String, Object> cursor : map.entrySet()) {...}
语法更佳。 - Chad Okere从参考资料如何在Java中迭代Map中提取:
在Java中,有几种迭代Map
的方法。让我们介绍最常见的方法并审查它们的优缺点。由于Java中的所有映射都实现了Map接口,因此以下技术将适用于任何映射实现(HashMap
、TreeMap
、LinkedHashMap
、Hashtable
等)。
方法#1:使用For-Each循环迭代条目。
这是最常见的方法,在大多数情况下都比较优选。如果需要在循环中同时使用映射键和值,则应使用此方法。
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
// Iterating over keys only
for (Integer key : map.keySet()) {
System.out.println("Key = " + key);
}
// Iterating over values only
for (Integer value : map.values()) {
System.out.println("Value = " + value);
}
这种方法比使用entrySet
迭代略微快一些(大约快10%),并且更加简洁。
方法3:使用迭代器进行迭代。
使用泛型:
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<Integer, Integer> entry = entries.next();
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
没有泛型:
Map map = new HashMap();
Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
Integer key = (Integer)entry.getKey();
Integer value = (Integer)entry.getValue();
System.out.println("Key = " + key + ", Value = " + value);
}
你也可以使用同样的技巧来遍历keySet
或values。
这种方法看起来可能有些冗余,但它有其自身的优点。首先,这是在旧版本的Java中遍历Map的唯一方式。另一个重要特性是,这是唯一允许你在迭代期间通过调用iterator.remove()
从Map中删除条目的方法。如果你在For-Each迭代期间尝试这样做,根据Javadoc,你将得到"不可预测的结果"。
从性能角度来看,这种方法与For-Each迭代相等。
方法#4:遍历键并搜索值(效率低下)。
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer key : map.keySet()) {
Integer value = map.get(key);
System.out.println("Key = " + key + ", Value = " + value);
}
ConcurrentMap
而言,在keySet()
上进行迭代通常会崩溃(无法保证早期收集的键存在相应的值)。另一方面,使用迭代器或条目是安全的(它们始终引用现有对象)。 - P Mareckiget()
总是 O(1),这就是 HashMap 的定义,而且用户要求使用 HashMap。我不明白为什么会有这么高的赞。如果你要引用别人的链接,请确保它与问题有实际关联。 - ohbrobigfor (Map.Entry<String, String> item : hashMap.entrySet()) {
String key = item.getKey();
String value = item.getValue();
}
您可以通过多种方式遍历Map
中的条目。像这样获取每个键和值:
Map<?,?> map = new HashMap<Object, Object>();
for(Entry<?, ?> e: map.entrySet()){
System.out.println("Key " + e.getKey());
System.out.println("Value " + e.getValue());
}
或者您可以使用以下方法获取键列表:
Collection<?> keys = map.keySet();
for(Object key: keys){
System.out.println("Key " + key);
System.out.println("Value " + map.get(key));
}
如果你只想获取所有值,而不关心键,可以使用以下方法:
Collection<?> values = map.values();
更聪明:
for (String key : hashMap.keySet()) {
System.out.println("Key: " + key + ", Value: " + map.get(key));
}
这要看情况而定。如果你需要访问每个entry的key和value,那么使用entrySet
方法。如果你只需要values,可以使用values()
方法。如果你只需要keys,可以使用keyset()
方法。
一个不好的实践是通过迭代所有的keys,并在循环内部始终使用map.get(key)
来获取value。如果你正在这样做,那么第一种我提到的方法适合你。