17

I have the following Java code:

public void myMethod (final Map pFeatureGroupsFromPackage) {

   final Set<String> keys = pFeatureGroupsFromPackage.keySet();

   for (final String key : keys) {
           tmpList = (List<FeatureKey>) pFeatureGroupsFromPackage.get(key);
    // do whatever
   }
}

I am getting a warning from "findBugs" telling the following:

Method myMethod makes inefficient use of keySet iterator instead of entrySet iterator. The warning is done at the tmpListassignment.

I do not understand why this is inefficient. In fact the keyslist is computed only once. Any comment? Thanks.

Luixv
  • 8,590
  • 21
  • 84
  • 121

7 Answers7

30

Instead of iterating over the keySet and calling get to get the corresponding value for each key, iterate over the entrySet:

final Set<Map.Entry<String, List<FeatureKey>>> entries = pFeatureGroupsFromPackage.entrySet();

for (Map.Entry<String, List<FeatureKey>> entry : entries) {
    String key = entry.getKey();
    List<FeatureKey> tmpList = entry.getValue();

    // do whatever
}

That way you don't have to do a lookup in the map for every key; you directly get the key and value in one go.

Also, declare your Map with type parameters:

public void myMethod (final Map<String, List<FeatureKey>> pFeatureGroupsFromPackage) {
    // ...
}
Jesper
  • 202,709
  • 46
  • 318
  • 350
  • Hi Jesper. Thanks for your answer. BTW, there are two syntax errors (one missing '>' and it should be entry instead of enty) :-) +1 and accepted for you – Luixv Mar 25 '11 at 10:15
5

you're getting all the keys and then you search for every key in the collection

a Map.EntrySet iteration would be much faster, a small example:

But you also should use generics...

Set entries = map.entrySet();
      Iterator entryIter = entries.iterator();
      System.out.println("The map contains the following associations:");
      while (entryIter.hasNext()) {
         Map.Entry entry = (Map.Entry)entryIter.next();
         Object key = entry.getKey();  // Get the key from the entry.
         Object value = entry.getValue();  // Get the value.
         System.out.println( "   (" + key + "," + value + ")" );
      }
sharpner
  • 3,857
  • 3
  • 19
  • 28
4

This could help you:

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);
}
brasofilo
  • 25,496
  • 15
  • 91
  • 179
1

Sample code:

for (Map.Entry < Integer, List < FeatureKey >>> i: map.entrySet()) {
    System.out.println(i.getValue() + " " + i.getKey()));
}
Gilsha
  • 14,431
  • 3
  • 32
  • 47
Mikhail
  • 2,690
  • 4
  • 28
  • 43
1

It could be that you are querying the map twice:

  • first for the keys,
  • and second for the values

Using entryset iterator will iterate over the map once.

Pang
  • 9,564
  • 146
  • 81
  • 122
0

Accessing the HashMap via keySet iterator is even faster than using the keySet iterator on the TreeMap.

developer
  • 9,116
  • 29
  • 91
  • 150
0

Hey Luixv, The reason using keysey iterator is less effective than entryset iteratot is that with the first option you still have to use the Map.get(key) lookeup which is avoided with the second option.

Assaf Adato
  • 237
  • 4
  • 14