Am acest câmp:
HashMap<String, HashMap> selects = new HashMap<String, HashMap>();
Pentru fiecare Hash<String, HashMap>
Am nevoie să creez un ComboBox
, ale cărui elemente sunt valoarea (care se întâmplă să fie ea însăși un HashMap) a lui HashMap <String, **HashMap**>
.
Cu titlu de demonstrație (nefuncțională):
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);
}
}
- În Java 8 folosind Lambda : stackoverflow.com/a/25616206/1503859 – > Por Nitin Mahesh.
- Java 8 folosind fluxuri : stackoverflow.com/a/32343195/1216775 , un avantaj al fluxurilor este că pot fi și ele paralelizate. – > Por akhil_mittal.
Știu că am întârziat un pic pentru asta, dar voi împărtăși și eu ce am făcut, în caz că ajută pe altcineva :
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.
}
- 115
- Nu-mi amintesc niciodată cum să scriu asta, așa că mă întorc mereu la același răspuns. Upvoted, pentru că acesta este un răspuns curat și acest cod este copiat și lipit în atât de multe locuri în proiectele mele, mulțumesc! – > .
- @Katu scrie doar yourmap..entrySet().for și autocompletarea IDE se va ocupa de asta. – > .
Lambda Expresie Java 8
În Java 1.8 (Java 8) acest lucru a devenit mult mai ușor prin utilizarea forEach din operațiunile agregate(Operațiuni de flux), care seamănă cu iteratorii din Iterable Interfață.
Trebuie doar să copiați și să lipiți declarația de mai jos în codul dvs. și să redenumiți metoda HashMap din hm în variabila HashMap pentru a tipări perechea cheie-valoare.
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));
Iată un exemplu în care un expresie Lambda este utilizată:
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
De asemenea, se poate utiliza Spliterator pentru același lucru.
Spliterator sit = hm.entrySet().spliterator();
UPDATE
Inclusiv linkurile de documentare către Oracle Docs.Pentru mai multe informații despre Lambda mergeți la acest link link și trebuie să citiți Operațiuni agregate iar pentru Spliterator, accesați acest link link.
- și presupun că nu putem avea variabile locale în interiorul domeniului de cuprindere fără să le declarăm finale. Am găsit
Local variable schedule defined in an enclosing scope must be final or effectively final
în timp ce se utilizează o variabilă declarată în afara corpului lambda, spre deosebire de închiderile din groovy. – > . - Dezavantajul utilizării lambdas este că nu puteți returna cealaltă metodă, în timp ce vă aflați în interiorul lambda. – > .
- Care este utilizarea spliteratorului aici? Folosiți fluxuri paralele? – > .
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: Aceasta este o abordare mai curată decât răspunsul meu (presupunând că folosim Java 5 sau o versiune ulterioară) – > .
- Utilizarea de argumente generice pe HashMap exterior pare să indice Java 5 sau o versiune ulterioară. [[ Dar m-am întrebat despre ce Java era vorba, deoarece HashMap-ul interior nu avea arge generice și se făcea o accesare a unui array pe un HashMap… dar este doar un „pseudocod” pentru a transmite întrebarea. ]] – > .
- Vrei să explici de ce nu pare să funcționeze pentru tine? Folosiți Java 5 sau o versiune ulterioară? Urmăm exemplul tău de cod, care nu pare să facă nimic cu caseta combo odată ce a fost creată. Sau valorile nu sunt în ordinea pe care o doriți? Sau aveai nevoie de chei în loc de valori în caseta combo? Cred că majoritatea ar fi de acord că oricare dintre cele 3 răspunsuri de până acum ar trebui să funcționeze bine, așa că probabil că există o problemă cu aplicarea răspunsului sau o altă problemă în altă parte, cu care am putea să vă ajutăm dacă ne dați mai multe informații. – > .
- ooohh…i stupiding =). Doar o singură întrebare cum se obține HashMap<this->String, HashMap<SomeInnerKeyType, String>> – > .
- @simply denis – Mi-e teamă că nu înțeleg întrebarea ta? Întrebi cum obții o referință la
HashMap<String, HashMap<SomeInnerKeyType, String>>
? Dacă bucla dvs. se află într-o metodă, ar trebui să puteți folosithis.selects
sau pur și simpluselects
? În caz contrar, ar trebui să transmiteți harta ca parametru la metoda care conține bucla. Sau întrebi cum să obții un anumit parametru interior al buclei?HashMap<SomeInnerKeyType, String>
pentru o anumită cheie (this->String
?) Ar trebui să folosițiselects.get(keyString)
. Dacă am înțeles complet greșit, vă rog să mă lămuriți. – > .
Fluxuri Java 8
Împreună cu forEach
metodă care acceptă un expresie lambda avem, de asemenea, și flux API-uri, în Java 8.
Iterați peste intrări (utilizând forEach și 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);
});
Avantajul fluxurilor este că pot fi paralelizate cu ușurință și pot fi utile atunci când avem la dispoziție mai multe procesoare. Trebuie pur și simplu să folosim parallelStream()
în loc de stream()
de mai sus. În cazul fluxurilor paralele, este mai logic să folosim forEach
ca forEachOrdered
nu ar face nicio diferență în ceea ce privește performanța. Dacă dorim să iterăm peste chei, putem utiliza sample.keySet()
iar pentru valori sample.values()
.
De ce forEachOrdered
și nu forEach
cu fluxuri?
De asemenea, fluxurile oferă forEach
dar comportamentul lui forEach
este în mod explicit nedeterminist, în timp ce forEachOrdered
execută o acțiune pentru fiecare element al acestui flux, în metoda ordinea de întâlnire a fluxului în cazul în care fluxul are o ordine de întâlnire definită. Deci forEach
nu garantează că ordinea va fi păstrată. Pentru mai multe informații, consultați și acest link.
Puteți itera peste un HashMap
(și multe alte colecții) folosind un iterator, de ex:
HashMap<T,U> map = new HashMap<T,U>();
...
Iterator it = map.values().iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
- Nu pot cu un astfel de design până la nivelul de mai jos – > .
- @Da, puteți. Puteți crea un iterator interior bazat pe
it.next()
. – > .
În general, fac același lucru ca și cx42net, dar nu creez în mod explicit o Intrare.
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));
}
}
Aceasta mi se pare cea mai intuitivă, cred că am prejudecăți împotriva iterației peste valorile unei hărți.
Utilizați 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"));
}
}
vedeți exemplul complet aici:
- Funcționează definitiv, eu îl folosesc în fiecare zi 🙂 Ce anume nu funcționează? După cum ați
HashMap<String, HashMap>
, ai avea nevoie de două bucle – una pentru HashMap-ul exterior și una pentru HashMap-ul interior. Btw – ar trebui să tastezi definitiv al doilea HashMap – nu știu ce stochezi în el, dar ceva de genul HashMap<String, HashMap<string, String>> – deși, din exemplul tău, se pare că ar trebui să foloseștiHashMap<String, Set<String>>
. Și încă un lucru – folosiți interfețe:Map<String, Map>
atunci când puteți. – > .