views:

438

answers:

5

In Python, you can have key,value pairs in a dictionary where you can loop through them, as shown below:

for k,v in d.iteritems():
    print k,v

Is there a way to do this with Java HashMaps?

+14  A: 

Yes - for example:

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);
}
Richard Fearn
Comparing this to the Python version reminds me why I gave up Java years ago.
Dave Kirby
+5  A: 

The HashMap.entrySet() will return beans of key value pairs similar to the dictionary.iteritems(). You can then loop through them.

I think is the closest thing to the Python version.

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

Something like that...

awregan
A: 

In Java, you can do the same like the following.

    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));
    }
Bragboy
Why the downvote ?
Bragboy
I didn't do the downvote, but this approach is less efficient than iterating over entryset. The `get()` has an extra cost on every iteration. It's at least not the "right" way to loop through a map. I can imagine that one downvoted because of that, how good your intent also is.
BalusC
@BalusC - yes, but creating the MapEntrySet iterator is (most likely) more expensive then creating a set iterator... I doubt, that it's a performance problem, and even if this was less performant, I'd **never ever** try to fix performance issues by *optimizing* for loops like this. (+1 from me, BTW).
Andreas_D
@Andreas_D: The creation of the entryset iterator isn't more expensive. The keyset uses the **same** iterator as the entryset. Also see [javadoc](http://java.sun.com/javase/6/docs/api/java/util/AbstractMap.html#keySet%28%29): *The subclass's iterator method returns a "wrapper object" over this map's entrySet() iterator.* The source code indeed confirms this: `private Iterator<Entry<K,V>> i = entrySet().iterator(); public K next() { return i.next().getKey(); }`
BalusC
+3  A: 

As shown in the answers, there are basically two ways to iterate over a Map (let's assume Map<String, String> in those examples).

  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));
    }
    

The second one is maybe more readable, but it has a performance cost of unnecessarily calling get() on every iteration. One may argument that creating the keyset iterator is less expensive because it doesn't need to take values into account. But believe it or not, the keySet().iterator() creates and uses the same iterator as entrySet().iterator(). The only difference is that in case of the keySet() the next() call of the iterator returns it.next().getKey() instead of it.next().

The AbstractMap#keySet()'s javadoc proves this:

The subclass's iterator method returns a "wrapper object" over this map's entrySet() iterator.

The AbstractMap source code also proves this. Here's an extract of keySet() method (somewhere around line 300 in Java 1.6):

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();
        }
    };
}

Note that readability should be preferred over premature optimization, but it's important to have this in mind.

BalusC