594

I have this field:

HashMap<String, HashMap> selects = new HashMap<String, HashMap>();

For each Hash<String, HashMap> I need to create a ComboBox, whose items are the value (which happens to be a HashMap itself) of HashMap <String, **HashMap**>.

By way of (non-functioning) demonstration:

for (int i=0; i < selects.size(); i++) {
    HashMap h = selects[i].getValue();
    ComboBox cb = new ComboBox();

    for (int y=0; y < h.size(); i++) {
        cb.items.add(h[y].getValue);
    }
}
Jarvis
  • 8,494
  • 3
  • 27
  • 58
Mediator
  • 14,951
  • 35
  • 113
  • 191

7 Answers7

1402

I know I'm a bit late for that one, but I'll share what I did too, in case it helps someone else :

HashMap<String, HashMap> selects = new HashMap<String, HashMap>();

for(Map.Entry<String, HashMap> entry : selects.entrySet()) {
    String key = entry.getKey();
    HashMap value = entry.getValue();

    // do what you have to do here
    // In your case, another loop.
}
Cyril N.
  • 38,875
  • 36
  • 142
  • 243
  • 128
    I never remember how to write this, so i always come back to this same answer. Upvoted, because this is clean answer and this code is copy pasted to so many places in my projects, thanks! – Katu Jan 23 '15 at 10:53
  • 16
    @Katu just write yourmap..entrySet().for and the IDE autocomplete will handle it. – AITAALI_ABDERRAHMANE Sep 11 '17 at 10:18
294

Lambda Expression Java 8

In Java 1.8 (Java 8) this has become lot easier by using forEach method from Aggregate operations(Stream operations) that looks similar to iterators from Iterable Interface.

Just copy paste below statement to your code and rename the HashMap variable from hm to your HashMap variable to print out key-value pair.

HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
/*
 *     Logic to put the Key,Value pair in your HashMap hm
 */

// Print the key value pair in one line.
hm.forEach((k,v) -> System.out.println("key: "+k+" value:"+v));

Here is an example where a Lambda Expression is used:

    HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
    Random rand = new Random(47);
    int i=0;
    while(i<5){
        i++;
        int key = rand.nextInt(20);
        int value = rand.nextInt(50);
        System.out.println("Inserting key: "+key+" Value: "+value);
        Integer imap =hm.put(key,value);
        if( imap == null){
            System.out.println("Inserted");
        }
        else{
            System.out.println("Replaced with "+imap);
        }               
    }

    hm.forEach((k,v) -> System.out.println("key: "+k+" value:"+v));

Output:

Inserting key: 18 Value: 5
Inserted
Inserting key: 13 Value: 11
Inserted
Inserting key: 1 Value: 29
Inserted
Inserting key: 8 Value: 0
Inserted
Inserting key: 2 Value: 7
Inserted
key: 1 value:29
key: 18 value:5
key: 2 value:7
key: 8 value:0
key: 13 value:11

Also one can use Spliterator for the same.

Spliterator sit = hm.entrySet().spliterator();

UPDATE


Including documentation links to Oracle Docs. For more on Lambda go to this link and must read Aggregate Operations and for Spliterator go to this link.

Luke H
  • 87
  • 1
  • 7
Nitin Mahesh
  • 3,802
  • 3
  • 30
  • 30
  • 1
    and I guess we cannot local variables inside enclosing scope without declaring them final. Got `Local variable schedule defined in an enclosing scope must be final or effectively final` while using variable declared outside lambda body, unlike closures in groovy. – Mahesha999 Dec 16 '16 at 14:32
  • 5
    The downside to using lambdas is that you cannot return the other method, while inside the lambda. – apscience Mar 30 '17 at 05:37
  • What is use of spliterator here? Are you using parallel streams? – akhil_mittal Oct 10 '18 at 12:47
  • If you are working on android, forEach call mentioned here requires API level 24. – A.J. Mar 13 '22 at 11:19
55

Map.values():

HashMap<String, HashMap<SomeInnerKeyType, String>> selects =
    new HashMap<String, HashMap<SomeInnerKeyType, String>>();

...

for(HashMap<SomeInnerKeyType, String> h : selects.values())
{
   ComboBox cb = new ComboBox();
   for(String s : h.values())
   {
      cb.items.add(s);
   }
}
Bert F
  • 85,407
  • 12
  • 106
  • 123
  • 2
    +1: This is a neater approach than my answer (assuming we're using Java 5 or later) – Oliver Charlesworth Nov 20 '10 at 21:05
  • 1
    Use of generic args on the outer HashMap would seem to indicate Java 5 or later. [[ But I did wonder about what Java this was since the inner HashMap didn't have generic args and there was an array access done on a HashMap... but its just some "pseudo" code for conveying the question. ]] – Bert F Nov 20 '10 at 21:17
  • 1
    Care to explain why it didn't seem to work for you? Are you using Java 5 or later? We're following your code example, which doesn't seem to do anything with the combo box once its created. Or are the values not in the order you want? Or did you need the keys instead of the values in the combo box? I think most would agree that any of the 3 answers so far should work fine, so likely there's a problem with apply the answer or another problem somewhere else that we may be able to help with if you give us more info. – Bert F Nov 20 '10 at 21:20
  • 1
    ooohh...i stupiding =). Only one question how get HashMapString, HashMap> – Mediator Nov 20 '10 at 21:34
  • 1
    @simply denis - I'm afraid I don't understand your question? Are you asking how do you get a reference to `HashMap>`? If your loop is in a method, you should be able to use `this.selects` or simply `selects`? Otherwise, you should pass the map in as a parameter to the method that contains the loop. Or are you asking how to get a specific inner `HashMap` for a given key (`this->String`?) You would use `selects.get(keyString)`. If I'm completely misunderstanding, please clarify. – Bert F Nov 20 '10 at 23:23
  • 1
    For a better answer, see Cyril N.'s answer below. – Zack Marrapese Mar 05 '13 at 13:47
32

Streams Java 8

Along with forEach method that accepts a lambda expression we have also got stream APIs, in Java 8.

Iterate over entries (Using forEach and Streams):

sample.forEach((k,v) -> System.out.println(k + "=" + v)); 
sample.entrySet().stream().forEachOrdered((entry) -> {
            Object currentKey = entry.getKey();
            Object currentValue = entry.getValue();
            System.out.println(currentKey + "=" + currentValue);
        });
sample.entrySet().parallelStream().forEach((entry) -> {
            Object currentKey = entry.getKey();
            Object currentValue = entry.getValue();
            System.out.println(currentKey + "=" + currentValue);
        });

The advantage with streams is they can be parallelized easily and can be useful when we have multiple CPUs at disposal. We simply need to use parallelStream() in place of stream() above. With parallel streams it makes more sense to use forEach as forEachOrdered would make no difference in performance. If we want to iterate over keys we can use sample.keySet() and for values sample.values().

Why forEachOrdered and not forEach with streams ?

Streams also provide forEach method but the behaviour of forEach is explicitly nondeterministic where as the forEachOrdered performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order. So forEach does not guarantee that the order would be kept. Also check this for more.

akhil_mittal
  • 23,309
  • 7
  • 96
  • 95
23

You can iterate over a HashMap (and many other collections) using an iterator, e.g.:

HashMap<T,U> map = new HashMap<T,U>();

...

Iterator it = map.values().iterator();

while (it.hasNext()) {
    System.out.println(it.next());
}
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
15

I generally do the same as cx42net, but I don't explicitly create an Entry.

HashMap<String, HashMap> selects = new HashMap<String, HashMap>();
for (String key : selects.keySet())
{
    HashMap<innerKey, String> boxHolder = selects.get(key);
    ComboBox cb = new ComboBox();
    for (InnerKey innerKey : boxHolder.keySet())
    {
        cb.items.add(boxHolder.get(innerKey));
    }
}

This just seems the most intuitive to me, I think I'm prejudiced against iterating over the values of a map.

panahi
  • 181
  • 2
  • 7
  • If you're iterating over the whole map, don't do lookups. Each hash look up may be O(1), but now you're doing n*O(1) of them for O(N) when the total number of hash lookups you need is 0. – Azeroth2b Aug 26 '22 at 22:22
9

Use entrySet,

/**
 *Output: 
D: 99.22
A: 3434.34
C: 1378.0
B: 123.22
E: -19.08

B's new balance: 1123.22
 */

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MainClass {
  public static void main(String args[]) {

    HashMap<String, Double> hm = new HashMap<String, Double>();

    hm.put("A", new Double(3434.34));
    hm.put("B", new Double(123.22));
    hm.put("C", new Double(1378.00));
    hm.put("D", new Double(99.22));
    hm.put("E", new Double(-19.08));

    Set<Map.Entry<String, Double>> set = hm.entrySet();

    for (Map.Entry<String, Double> me : set) {
      System.out.print(me.getKey() + ": ");
      System.out.println(me.getValue());
    }

    System.out.println();

    double balance = hm.get("B");
    hm.put("B", balance + 1000);

    System.out.println("B's new balance: " + hm.get("B"));
  }
}

see complete example here:

Suresh Maidaragi
  • 2,173
  • 18
  • 25
icyrock.com
  • 27,952
  • 4
  • 66
  • 85
  • 2
    It definitively works, I use it every day :) What exactly doesn't work? As you have `HashMap`, you would need two loops - one for the outer and one for the inner HashMap. Btw - you should definitively type the second HashMap - don't know what you store in it, but something like HashMap> - though, from your example, it seems you should use `HashMap>`. And another thing - use interfaces: `Map` when you can. – icyrock.com Nov 20 '10 at 21:27