像Python字典一样循环Java HashMap?

8
在Python中,您可以使用字典来存储键值对,并且可以通过循环遍历它们,如下所示:
for k,v in d.iteritems():
    print k,v

有没有一种方法可以使用Java HashMap来实现这个?

5个回答

21
是的 - 例如:
Map<String, String> map = new HashMap<String, String>();
// add entries to the map here

for (Map.Entry<String, String> entry : map.entrySet()) {
    String k = entry.getKey();
    String v = entry.getValue();
    System.out.printf("%s %s\n", k, v);
}

9
与 Python 版本相比,这让我想起多年前为何放弃了 Java。 - Dave Kirby

6

如答案所示,基本上有两种方法可以迭代一个Map(在这些例子中假设为Map<String, String>)。

  1. Iterate over Map#entrySet():

    for (Entry<String, String> entry : map.entrySet()) {
        System.out.println(entry.getKey() + "=" + entry.getValue());
    }
    
  2. Iterate over Map#keySet() and then use Map#get() to get the value for every key:

    for (String key : map.keySet()) {
        System.out.println(key + "=" + map.get(key));
    }
    
第二种方法可能更易读,但是它会产生性能损失,因为在每次迭代中都会不必要地调用get()。有人可能会认为创建键集迭代器的成本较低,因为它不需要考虑值。但是不管你信不信,keySet().iterator() 创建并使用与 entrySet().iterator() 相同的迭代器。唯一的区别在于,在keySet() 的情况下,迭代器的next() 调用返回的是it.next().getKey()而不是it.next()

AbstractMap#keySet()的Javadoc证明了这一点:

子类的迭代器方法返回此映射条目集合上的“包装对象”。

此外,AbstractMap源代码也证明了这一点。以下是keySet() 方法的摘录(Java 1.6 中大约在第300行左右):

public Iterator<K> iterator() {
    return new Iterator<K>() {
        private Iterator<Entry<K,V>> i = entrySet().iterator(); // <-----

        public boolean hasNext() {
            return i.hasNext();
        }

        public K next() {
            return i.next().getKey(); // <-----
        }

        public void remove() {
            i.remove();
        }
    };
}

请注意,在过早优化之前应优先考虑可读性,但要记住这一点。

6

3
Set<Map.Entry> set = d.entrySet();
for(Map.Entry i : set){
  System.out.println(i.getKey().toString() + i.getValue().toString);
}

Something like that...


1
在Java中,您可以像以下方式一样执行相同的操作。
    HashMap<String, String> h = new HashMap<String, String>();
    h.put("1","one");
    h.put("2","two");
    h.put("3","three");

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

我没有进行负面评价,但是这种方法比遍历entryset的效率要低。每次迭代都需要额外的get()成本。这至少不是遍历map的“正确”方式。我可以想象,有人因为这个原因对你进行了负面评价,无论你的意图有多好。 - BalusC
2
@BalusC - 是的,但创建MapEntrySet迭代器比创建set迭代器更昂贵...我怀疑这不是性能问题,即使这样做的性能较差,我也永远不会尝试通过像这样优化循环来解决性能问题。(顺便说一句,我给你点赞+1)。 - Andreas Dolk
2
@Andreas_D:创建entryset迭代器并不更昂贵。keyset使用与entryset相同的迭代器。还请参阅javadoc子类的iterator方法返回一个“包装器对象”,该对象覆盖了此地图的entrySet()迭代器。源代码确实证实了这一点:private Iterator<Entry<K,V>> i = entrySet().iterator(); public K next() { return i.next().getKey(); } - BalusC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接