Loop Java HashMap like Python Dictionary?
Asked Answered
J

6

9

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?

Jumbala answered 1/7, 2010 at 12:6 Comment(0)
W
21

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);
}
Whistling answered 1/7, 2010 at 12:11 Comment(1)
Comparing this to the Python version reminds me why I gave up Java years ago.Breeches
C
6

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.

Crowl answered 1/7, 2010 at 12:11 Comment(0)
C
6

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.

Charity answered 1/7, 2010 at 14:1 Comment(0)
R
3
Set<Map.Entry> set = d.entrySet();
for(Map.Entry i : set){
  System.out.println(i.getKey().toString() + i.getValue().toString);
}

Something like that...

Rockbound answered 1/7, 2010 at 12:13 Comment(0)
S
1

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));
    }
Serai answered 1/7, 2010 at 12:14 Comment(3)
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.Charity
@Charity - 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).Piet
@Andreas_D: The creation of the entryset iterator isn't more expensive. The keyset uses the same iterator as the entryset. Also see javadoc: 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(); }Charity
B
0

You can also use one liner using method references as in below example

Map<String, Object> dict=new TreeMap<String, Object>();
    dict.put("age", 20);
    dict.put("height", 1.75);
    dict.put("country", "India");
    dict.put("profession", "developer");
    dict.entrySet().stream().forEach(System.out::println);

Output will be

age=20
country=India
height=1.75
profession=developer
Bridgetbridgetown answered 23/9 at 23:16 Comment(2)
Maybe you should edit your answer and indicate that your code uses the stream API which was added in Java 8 - since the question was posted in 2010 when the latest Java version was 1.6Superstructure
Java 1.6 and 1.7 are end of life so your comment doesn't make any senseBridgetbridgetown

© 2022 - 2024 — McMap. All rights reserved.