2010-11-20 11 views
347

mam tego pola:Jak dla każdej mapy?

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

dla każdego Hash<String, HashMap> muszę stworzyć ComboBox, którego elementy są wartością (co dzieje się sama HashMap) od HashMap <String, **HashMap**>.

drodze (nie funkcjonujące) wykazanie:

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

W języku Java 8 przy użyciu Lambda: http://stackoverflow.com/a/25616206/1503859 –

Odpowiedz

856

Wiem, że trochę późno dla tego jednego, ale będę dzielić co zrobiłem też w przypadku, gdy ktoś inny pomaga:

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

Nigdy nie pamiętam, jak to napisać, więc zawsze wracam do tej samej odpowiedzi. Rewizja, ponieważ jest to czysta odpowiedź i ten kod jest kopiowany wklejony do tylu miejsc w moich projektach, dzięki! – Katu

+1

@Katu po prostu napisz yourmap..entrySet(). Dla i autouzupełniania IDE zajmie się nim. –

2

użytkowania entrySet patrz przykład tutaj:

+0

icyrock.com, nie działa – Mediator

+1

To zdecydowanie działa, ja go używam codziennie :) Co dokładnie nie działa? Ponieważ masz 'HashMap ', potrzebujesz dwóch pętli - jednej dla zewnętrznej i drugiej dla wewnętrznej HashMap. Btw - powinieneś definitywnie wpisać drugą HashMap - nie wiesz, co w niej przechowujesz, ale coś w rodzaju HashMap > - choć z twojego przykładu, wydaje się, że powinieneś użyć 'HashMap > '. I jeszcze jedno - użyj interfejsów: 'Map ' kiedy możesz. –

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: To jest lepsze podejście niż moja odpowiedź (zakładając, że używamy języka Java 5 lub nowszego). –

+0

Użycie ogólnych argumentów na zewnętrznej mapie HashMap wydaje się wskazywać na język Java 5 lub nowszy. [[Ale zastanawiałem się, co to jest Java, ponieważ wewnętrzna HashMap nie miała generycznych argumentów i był dostęp do tablicy na HashMap ... ale to tylko jakiś "pseudo" kod do przekazania pytania. ]] –

+0

Bert F, nie pracuj – Mediator

13

Można iteracyjne nad HashMap (i wielu innych kolekcji) przy użyciu iterację, np:

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

... 

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

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

Nie mogę z takim projektem do poziomu poniżej – Mediator

+2

@ Tak, możesz. Możesz stworzyć wewnętrzny iterator oparty na 'it.next()'. –

12

ja generalnie tak samo jak cx42net, ale nie jawnie utworzyć wpis.

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

To wydaje mi się najbardziej intuicyjne, wydaje mi się, że jestem uprzedzony do powtarzania wartości mapy.

153

Lambda Expression Java 8

W Javie 1.8 (Java 8) stało się dużo łatwiejsze przy użyciu foreach metody z operacji agregaty (operacji Stream), który wygląda podobnie do iteratorów od Iterable Interfejs.

Wystarczy skopiować pasty poniżej rachunku do kodu i zmienić nazwę zmienną HashMap z hm do zmiennej HashMap aby wydrukować parę klucz-wartość.

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

Poniżej przedstawiono przykład, w którym wykorzystuje się N Ekspresja:

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 

Ponadto można stosować Spliterator tego samego.

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

UPDATE


tym łącza do dokumentacji Oracle Docs. Aby uzyskać więcej informacji na temat Lambda przejdź do tego link i przeczytaj Aggregate Operations, a dla Spliteratora przejdź do tego link.

+0

i domyślam się, że nie możemy zmiennych lokalnych wewnątrz obejmujących zakres bez deklarowania ich ostateczne. "Lokalny harmonogram zmiennych zdefiniowany w otaczającym zakresie musi być końcowy lub efektywny końcowy" przy użyciu zmiennej zadeklarowanej poza ciałem lambda, w przeciwieństwie do zamknięć w groovy. – Mahesha999

+2

Minusem używania lambd jest to, że nie można zwrócić drugiej metody, podczas gdy w lambda. – apscience

5

Jak już wspomniano, w języku Java 8 mamy metodę forEach, która akceptuje lambda expression. Ale mamy także interfejsy API stream.

iteracyjne nad wpisami (przy użyciu foreach i strumieni):

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

Zaletą jest strumienie mogą być parallelized łatwo i może być przydatna, gdy mamy wiele procesorów do dyspozycji. Po prostu potrzebujemy użyć parallelStream() zamiast powyższego stream(). W przypadku strumieni równoległych bardziej sensowne jest używanie wartości forEach, ponieważ nie ma to wpływu na wydajność. Jeśli chcemy iterować po kluczach, możemy użyć sample.keySet() i dla wartości sample.values().

Dlaczego forEachOrdered, a nie forEach ze strumieniami?

Strumienie zapewniają również forEach metody, ale zachowanie forEach jest wyraźnie niedeterministyczny gdzie jako forEachOrdered wykonuje czynność, dla każdego elementu z tego strumienia, w celu zetknięcie strumienia jeżeli strumień posiada określoną kolejność spotkań. Tak więc forEach nie gwarantuje, że zamówienie zostanie zachowane. Sprawdź także this, aby uzyskać więcej informacji.

+0

Proszę nie zamieszczać identycznych odpowiedzi na wiele pytań. Napisz jedną dobrą odpowiedź, a następnie głosuj/oznacz, aby zamknąć pozostałe pytania jako duplikaty. Jeśli pytanie nie jest duplikatem, * dostosuj swoje odpowiedzi na pytanie. * – durron597

+0

Poprawiono odpowiedź odpowiednio. –

Powiązane problemy