2010-11-20 11 views
347

Ho questo campo:Come per ogni hashmap?

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

Per ogni Hash<String, HashMap> necessario creare un ComboBox, i cui elementi sono il valore (che risulta essere un HashMap stesso) di HashMap <String, **HashMap**>.

A titolo di (non funzionante) dimostrazione:

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

In Java 8 utilizzando Lambda: http://stackoverflow.com/a/25616206/1503859 –

risposta

856

so di essere un po 'tardi per quello, ma io condividere quello che ho fatto troppo, nel caso in cui aiuta a qualcun altro:

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. 
} 
+40

Non ricordo mai come scriverlo, quindi torno sempre a questa stessa risposta. Votato, perché questa è una risposta pulita e questo codice è stato copiato in così tanti posti nei miei progetti, grazie! – Katu

+1

@Katu scrivi semplicemente yourmap..entrySet(). For e il completamento automatico IDE lo gestirà. –

2
+0

icyrock.com, non funziona – Mediator

+1

Funziona definitivamente, lo uso tutti i giorni :) Che cosa esattamente non funziona? Dato che hai 'HashMap ', avrai bisogno di due cicli: uno per l'esterno e uno per la HashMap interna. Btw - dovresti digitare la seconda HashMap in modo definitivo - non so cosa ci hai messo dentro, ma qualcosa come HashMap > - sebbene, dal tuo esempio, sembra che dovresti usare 'HashMap > '. E un'altra cosa: usa le interfacce: 'Mappa ' quando puoi. –

43

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

+1: questo è un approccio più ordinato della mia risposta (supponendo che stiamo usando Java 5 o successivo) –

+0

L'uso di argomenti generici sulla HashMap esterna sembrerebbe indicare Java 5 o successivo. [[Ma mi sono interrogato su ciò che Java era, dato che l'HashMap interno non aveva argomenti generici e c'era un accesso in array su una HashMap ... ma era solo un codice "pseudo" per trasmettere la domanda. ]] –

+0

Bert F, non funziona – Mediator

13

È possibile iterazioni su una HashMap (altri e molte collezioni) utilizzando un iteratore, ad esempio:

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

... 

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

while (it.hasNext()) { 
    System.out.println(it.next()); 
} 
+1

Non posso con un tale design fino al livello inferiore a – Mediator

+2

@ Sì, è possibile. È possibile creare un iteratore interno basato su 'it.next()'. –

12

io in genere faccio lo stesso di cx42net, ma io non crea esplicitamente una voce.

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

Questo sembra proprio il più intuitivo per me, penso di essere prevenuto contro l'iterazione sui valori di una mappa.

153

Lambda Espressione Java 8

In Java 1.8 (Java 8) questo è diventato molto più facile utilizzando forEach metodo da operazioni di aggregazione (operazioni Ruscello) che sembra simile a iteratori da Interfaccia Iterable.

basta copiare e incollare di seguito comunicato al codice e rinominare il variabile HashMap da hm alla variabile HashMap di stampare coppia chiave-valore.

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

Ecco un esempio in cui viene utilizzato un Expression Lambda:

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 

Inoltre si può usare Spliterator per lo stesso.

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

UPDATE


Compreso collegamenti alla documentazione a Oracle Docs. Per ulteriori informazioni su Lambda andare a questo link e leggere Aggregate Operations e per Spliterator andare a questo link.

+0

e suppongo che non possiamo variabili locali all'interno del campo di applicazione senza dichiararle definitive. Got 'La programmazione delle variabili locali definita in un ambito che racchiude deve essere definitiva o effettivamente definitiva 'mentre si utilizza la variabile lambda esterna dichiarata, a differenza delle chiusure in groovy. – Mahesha999

+2

Lo svantaggio dell'uso di lambda è che non è possibile restituire l'altro metodo, mentre all'interno del lambda. – apscience

5

Come già accennato, in Java 8 abbiamo il metodo forEach che accetta uno lambda expression. Ma abbiamo anche le API stream.

iterare voci (Usando forEach e 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); 
     }); 

Il vantaggio con i flussi è che possono essere parallelizzati facilmente e possono essere utili quando i più CPU a disposizione. Abbiamo semplicemente bisogno di usare parallelStream() al posto di stream() sopra. Con flussi paralleli ha più senso usare forEach come forEachOrdered non farebbe alcuna differenza nelle prestazioni. Se vogliamo iterare sui tasti, possiamo usare sample.keySet() e per i valori sample.values().

Perché forEachOrdered e non forEach con flussi?

Streams forniscono anche forEach metodo, ma il comportamento di forEach è esplicitamente non deterministico dove il forEachOrdered esegue un'azione per ogni elemento di questo flusso, nell'ordine incontro del flusso se il flusso ha un ordine incontro definito. Quindi forEach non garantisce che l'ordine venga mantenuto. Controlla anche this per ulteriori informazioni.

+0

Si prega di non pubblicare risposte identiche a più domande. Pubblica una buona risposta, quindi vota/contrassegna per chiudere le altre domande come duplicati. Se la domanda non è un duplicato, * adatta le tue risposte alla domanda. * – durron597

+0

Aggiorna la risposta di conseguenza. –