java collections - keyset() vs entrySet() in map

121.3k views Asked by At

I put a string array elements is a map where elements of string array is key and frequency of word is value, e.g.:

String[] args = {"if","it","is","to","be","it","is","up","me","to","delegate"};

then the map will have entries like [ if:1, it:2 .... ]

Set<String> keys = m.keySet();
System.out.println("keyset of the map : "+keys);

prints all keys: "if","it","is","to","be","it","is","up","me","to","delegate"

Set<Map.Entry<String, Integer>> entrySet = m.entrySet();
Iterator<Map.Entry<String, Integer>> i = entrySet.iterator();
while(i.hasNext()){
    Map.Entry<String, Integer> element = i.next();
    System.out.println("Key: "+element.getKey()+" ,value: "+element.getValue());
}

prints all key values pairs :

Using entry set prints all values:

Key: if ,value: 1
Key: it ,value: 2
Key: is ,value: 2
Key: to ,value: 2
Key: be ,value: 1
Key: up ,value: 1
Key: me ,value: 1
Key: delegate ,value: 1

But the block of code below should print exactly the same output as above, but it does not:

Iterator<String> itr2 = keys.iterator();
while(itr2.hasNext()){
    //System.out.println(itr1.next()+" ");
    //System.out.println(m.get(itr1.next())+" ");
    System.out.println("Key: "+itr2.next()+" ,value: "+m.get(itr2.next()));
}

It prints:

Key: if ,value: 2
Key: is ,value: 2
Key: be ,value: 1
Key: me ,value: 1

But if we uncomment line 1 in the while loop i.e

System.out.println(itr1.next()+" ");

and comment the line

System.out.println("Key: "+itr2.next()+" ,value: "+m.get(itr2.next()));

Then we get all keys: {"if","it","is","to","be","it","is","up","me","to","delegate"};

If we use m.get() with itr2.next(), then the iterator does not have few keys!

5

There are 5 answers

3
Natix On BEST ANSWER

Every call to the Iterator.next() moves the iterator to the next element. If you want to use the current element in more than one statement or expression, you have to store it in a local variable. Or even better, why don't you simply use a for-each loop?

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

Moreover, loop over the entrySet is faster, because you don't query the map twice for each key. Also Map.Entry implementations usually implement the toString() method, so you don't have to print the key-value pair manually.

for (Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry);
}
0
kosa On

An Iterator moves forward only, if it read it once, it's done. Your

m.get(itr2.next());

is reading the next value of itr2.next();, that is why you are missing a few (actually not a few, every other) keys.

3
Vincent Ramdhanie On

Every time you call itr2.next() you are getting a distinct value. Not the same value. You should only call this once in the loop.

Iterator<String> itr2 = keys.iterator();
    while(itr2.hasNext()){
        String v = itr2.next();
        System.out.println("Key: "+v+" ,value: "+m.get(v));
    }
0
beingmanish On

To make things simple , please note that every time you do itr2.next() the pointer moves to the next element i.e. here if you notice carefully, then the output is perfectly fine according to the logic you have written .
This may help you in understanding better:

1st Iteration of While loop(pointer is before the 1st element):
Key: if ,value: 2 {itr2.next()=if; m.get(itr2.next()=it)=>2}

2nd Iteration of While loop(pointer is before the 3rd element):
Key: is ,value: 2 {itr2.next()=is; m.get(itr2.next()=to)=>2}

3rd Iteration of While loop(pointer is before the 5th element):
Key: be ,value: 1 {itr2.next()="be"; m.get(itr2.next()="up")=>"1"}

4th Iteration of While loop(pointer is before the 7th element):
Key: me ,value: 1 {itr2.next()="me"; m.get(itr2.next()="delegate")=>"1"}

Key: if ,value: 1
Key: it ,value: 2
Key: is ,value: 2
Key: to ,value: 2
Key: be ,value: 1
Key: up ,value: 1
Key: me ,value: 1
Key: delegate ,value: 1

It prints:

Key: if ,value: 2
Key: is ,value: 2
Key: be ,value: 1
Key: me ,value: 1

0
RED.Skull On

Traversal over the large map entrySet() is much better than the keySet(). Check this tutorial how they optimise the traversal over the large object with the help of entrySet() and how it helps for performance tuning.