关于Java:通过一个哈希图迭代

Iterate through a HashMap

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
How to efficiently iterate over each entry in a 'Map'?

迭代HashMap中的项目的最佳方法是什么?


如果您只对这些键感兴趣,那么可以遍历映射的keySet()

1
2
3
4
5
Map<String, Object> map = ...;

for (String key : map.keySet()) {
    // ...
}

如果只需要这些值,请使用values()

1
2
3
for (Object value : map.values()) {
    // ...
}

最后,如果您同时需要键和值,请使用entrySet()

1
2
3
4
5
for (Map.Entry<String, Object> entry : map.entrySet()) {
    String key = entry.getKey();
    Object value = entry.getValue();
    // ...
}

一个警告:如果你想在迭代过程中删除项目,你需要通过一个迭代器来完成(参见Karim79的答案)。但是,更改项目值是可以的(参见Map.Entry)。


像这样迭代entrySet()

1
2
3
4
5
6
7
8
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的信息。


从引用中提取如何在Java中遍历地图:

在Java中迭代EDCOX1的1种方法有几种方式。让我们回顾一下最常用的方法,回顾一下它们的优缺点。由于Java中的所有映射都实现了MAP接口,下面的技术将用于任何映射实现(EDCOX1,12,EDCOX1,13,EDCOX1,14,EDCOX1,15,等等)。

方法1:使用for each循环迭代条目。

这是最常见的方法,在大多数情况下更可取。如果循环中同时需要映射键和值,则应该使用它。

1
2
3
4
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());
}

注意,每个循环都是在Java 5中引入的,所以这种方法只适用于新版本的语言。另外,如果您试图在一个为空的映射上迭代,for-each循环将抛出NullPointerException,因此在迭代之前,您应该始终检查是否有空引用。

方法2:使用for each循环迭代键或值。

如果只需要映射中的键或值,则可以迭代键集或值,而不是EntrySet。

1
2
3
4
5
6
7
8
9
10
11
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:使用迭代器迭代。

使用泛型:

1
2
3
4
5
6
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());
}

无仿制药:

1
2
3
4
5
6
7
8
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或值进行迭代。

这种方法看起来可能是多余的,但它有自己的优点。首先,它是在旧版本的Java中迭代地图的唯一方法。另一个重要特性是,它是唯一允许您在迭代期间通过调用iterator.remove()从映射中删除条目的方法。根据JavaDoc,如果在每次迭代中尝试这样做,将得到"不可预知的结果"。

从性能的角度来看,这个方法在每次迭代中等于。

方法4:迭代键并搜索值(效率低下)。

1
2
3
4
5
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);
}

对于方法1,这可能看起来是一种更清洁的替代方法,但实际上,它非常缓慢且效率低下,因为通过键获取值可能很耗时(在不同的映射实现中,此方法比方法1慢20%-200%)。如果安装了findbugs,它将检测到这一点并警告您迭代效率低下。应避免使用这种方法。

结论:

如果只需要映射中的键或值,请使用方法2。如果你坚持旧版本的Java(小于5)或者计划在迭代过程中删除条目,则必须使用方法3。否则使用方法1。


1
2
3
4
for (Map.Entry<String, String> item : hashMap.entrySet()) {
    String key = item.getKey();
    String value = item.getValue();
}


您可以用多种方式迭代Map中的条目。获取每个键和值,如下所示:

1
2
3
4
5
Map<?,?> map = new HashMap<Object, Object>();
for(Entry<?, ?> e: map.entrySet()){
    System.out.println("Key" + e.getKey());
    System.out.println("Value" + e.getValue());
}

或者你可以用

1
2
3
4
5
Collection<?> keys = map.keySet();
for(Object key: keys){
    System.out.println("Key" + key);
    System.out.println("Value" + map.get(key));
}

如果您只想获取所有的值,而不关心这些键,那么可以使用:

1
Collection<?> values = map.values();

更聪明的:

1
2
3
for (String key : hashMap.keySet()) {
    System.out.println("Key:" + key +", Value:" + map.get(key));
}


视情况而定。如果您知道您将需要每个条目的键和值,那么就通过entrySet。如果您只需要这些值,那么这里有values()方法。如果你只需要钥匙,那就用keySet()

一个糟糕的做法是遍历所有键,然后在循环中,总是执行map.get(key)来获取值。如果你这样做,那么我写的第一个选择就是为你。