迭代HashMap

burntsugar 3244 java iteration loops hashmap

可能重复:
如何有效地迭代"地图"中的每个条目?

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

harto.. 4595

如果您只对键感兴趣,可以遍历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();
    // ...
}

一个警告:如果你想在迭代中删除项目,你需要通过迭代器这样做(参见karim79的回答).但是,更改项目值是可以的(请参阅参考资料Map.Entry).

  • 当您需要键和值时,使用entrySet更有效.如果你只需要一个或者另一个,那就使用那个:http://stackoverflow.com/questions/3870064/performance-considerations-for-keyset-and-entryset-of-map/6927754#6927754 (17认同)
  • 更重要的一点是,keySet()返回的Set和values()返回的Collection都由原始Map支持.也就是说,如果你对它们进行任何修改,它们将反映在Map中,但是,它们都不支持add()和addAll()方法,即你不能将新的键添加到Set或new值在收藏中. (4认同)
  • 那么如何同时循环2个地图呢?使用entrySet方法?我尝试使用&&但是它很有用 (3认同)
  • 使用两个迭代器.有关迭代器的示例用法,请参阅接受的答案. (2认同)

karim79.. 3167

通过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.

  • @ karim79您如何看待以下方式:`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()); }` (445认同)
  • for(Map.Entry <String,Object> cursor:map.entrySet()){...}`语法要好得多. (108认同)
  • 虽然是旧式,但这将有助于避免在下面的答案中针对新foreach样式的ConcurrentModificationExceptions.例如,您可以通过单独的迭代器删除. (34认同)
  • @vimukthi你是什么意思解决这个问题?只需删除`it.remove();`行. (26认同)
  • 通过调用'it.remove(); '如果这个地图是一个类变量,你正在清空地图,使其无法重复使用.你对此有什么解决方案吗? (10认同)
  • 我意外地来到这里,为什么我们在这里做`Iterator.remove()?OP只是想要一个迭代`Map`的最佳方法 (7认同)
  • Iterator接口从1.2开始是通用的.它需要是Iterator <E> (4认同)
  • 每个人都说`for(Map.Entry <String,Object> cursor:map.entrySet())`比这更好,忽略了你仍然会收到使用该方法的`ConcurrentModificationException`的事实.选择的答案仍然是迭代"Map"的最佳方法. (4认同)
  • @ harto的答案更好,因为它告诉读者如何在各种情况下实际使用它.您的解决方案的应用范围很小.非常小. (2认同)

小智.. 823

摘自参考如何在Java中迭代地图:

Map在Java中有几种迭代方法.让我们回顾一下最常用的方法,并回顾它们的优缺点.由于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());
}

请注意,For-Each循环是在Java 5中引入的,因此该方法仅适用于该语言的较新版本.NullPointerException如果您尝试迭代一个null的映射,也会抛出For-Each循环,因此在迭代之前,应始终检查空引用.

方法#2:使用For-Each循环迭代键或值.

如果只需要地图中的键或值,则可以迭代keySet或值而不是entrySet.

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或值.

这种方法可能看起来多余,但它有其自身的优点.首先,它是在旧版Java中迭代地图的唯一方法.另一个重要特性是它是唯一允许您在迭代期间通过调用从地图中删除条目的方法iterator.remove().如果您尝试在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);
}

对于方法#1而言,这可能看起来更清晰,但实际上它非常慢且效率低,因为通过键获取值可能非常耗时(不同Map实现中的此方法比方法#1慢20%-200%) ).如果安装了FindBugs,它将检测到这一点并警告您低效的​​迭代.应该避免这种方法.

结论:

如果只需要地图中的键或值,请使用方法#2.如果您遇到旧版本的Java(少于5个)或计划在迭代期间删除条目,则必须使用方法#3.否则使用方法#1.

  • @arvind方法#4如何效率低下?根据定义,对于HashMap,调用`get()`总是O(1).这是HashMap的定义,用户要求HashMap.我不明白为什么这是如此高度的投票.如果您要引用其他人的链接,请确保它对于提出的问题确实有意义. (2认同)

gabor.. 160

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


codethulhu.. 98

您可以通过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();


小智.. 68

智慧:

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

  • 每次迭代的map.get(key)都不是更聪明 - 它的速度更慢 (14认同)
  • 这实际上取决于你是否需要钥匙.如果没有,使用entrySet()会更有效,因为hashCode()不会被调用. (9认同)

Gary Kephart.. 47

要看.如果你知道你将需要每个条目的密钥和值,那么请通过entrySet.如果你只需要这些值,那就是values()方法.如果你只需要钥匙,那就用吧keyset().

一个不好的做法是迭代所有的键,然后在循环中,总是map.get(key)去获取值.如果你这样做,那么我写的第一个选项就是你.


归档时间:

查看次数:

3631365 次

最近记录:

1 年,10 月 前