2012-03-18 12 views
6

Korzystanie z nowych kolekcji z Guawy Google, http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplainedJak powtórzyć Multimap w zamówieniu reklamowym?

Jak wykonać pętlę w MultiMap dla każdego klucza w kolejności wstawiania?

Przykładowo

multimap = new HashMultiMap<String,String>(); 
multimap.put("1", "value1"); 
multimap.put("1", "value2"); 
multimap.put("1", "value3"); 

multimap.put("2", "value11"); 
multimap.put("2", "value22"); 
multimap.put("2", "value33"); 

multimap.put("3", "value111"); 
multimap.put("3", "value222"); 
multimap.put("3", "value333"); 

w każdej iteracji potrzebne

"value1", "value11", "value111"; 

następnie następnej pętli

"value2", "value22", "value222"; 

itd:

"value3", "value33", "value333"; 
+4

Kolekcje "Hash *" nie zachowują zamówienia reklamowego. – SLaks

+0

Wygląda na to, że potrzebuję użyć Tabeli, a nie MultiMap – KJW

Odpowiedz

11

Nie jestem do końca pewien jakie są twoje potrzeby (lub konkretny przypadek użycia), ale spróbuję zgadnąć. Inne odpowiedzi sugerują użycie Linked * Multimap lub Immutable, ale aby uzyskać pożądany wynik (pokazany w pytaniu) z Multimap będziesz musiał stworzyć jakąś fantazyjną Mapę (omówię to później) lub na przykład utworzę trzy tymczasowe kolekcje zawierające pierwsze, drugie i trzecie wartości dla każdego klucza (będą one w kolejności wstawiania, jeśli użyjesz jednej z sugerowanych implementacji Multimap). Korzystnie byłoby jedną ListMultimaps jak można iterować multimap.keySet() dostać list z wartościami dostępnymi przez index:

final ListMultimap<String,String> multimap = LinkedListMultimap.create(); 
// put values from question here 

final List<Object> firstValues = Lists.newArrayList(); 
for (final String key: multimap.keySet()) { 
    firstValues.add(multimap.get(key).get(0)); 
}  
System.out.println(firstValues); 
// prints [value1, value11, value111] 
// similar for multimap.get(key).get(1) and so on 

ale minusem jest to, że trzeba będzie utworzyć trzy listy do ciebie przykład, co czyni to rozwiązanie raczej nieelastyczny.Więc może to będzie lepiej umieścić {pierwszy, drugi, trzeci} Wartości kolekcję na mapie>, co doprowadza mnie do punktu:


Może należy użyć Table zamiast?

Table został zaprojektowany jako kolekcji, która kojarzy uporządkowaną parę kluczy, zwany klucz wiersza i kolumny klucza, z jednej wartości i, co ważniejsze, tutaj ma wiersza i kolumny poglądy. Użyję ArrayTable tutaj:

final ArrayTable<String, Integer, Object> table = ArrayTable.create(
    ImmutableList.of("1", "2", "3"), ImmutableList.of(0, 1, 2)); 

table.put("1", 0, "value1"); 
table.put("1", 1, "value2"); 
table.put("1", 2, "value3"); 

table.put("2", 0, "value11"); 
table.put("2", 1, "value22"); 
table.put("2", 2, "value33"); 

table.put("3", 0, "value111"); 
table.put("3", 1, "value222"); 
table.put("3", 2, "value333"); 

for (final Integer columnKey : table.columnKeyList()) { 
    System.out.println(table.column(columnKey).values()); 
} 
// prints: 
// [value1, value11, value111] 
// [value2, value22, value222] 
// [value3, value33, value333] 

ja celowo wykorzystywane String na klucze wierszy, które są [1, 2, 3, ...] liczb całkowitych rzeczywistości (jak to zrobiłeś w pytaniu) i całkowitymi dla kolumn kluczy zaczynając od 0 ([0, 1, 2, ...]), aby pokazać podobieństwo do poprzedniego przykładu, korzystając z kolekcji List get(int) dla kolekcji wartości multimap.

nadzieję, że będzie pomocny, głównie w celu ustalenia, co chcesz;)

PS: Używam tutaj ArrayTable, ponieważ ma on lepszy sposób tworzenia ustalonego zestawu (wszechświata) wartości wierszy/kluczy niż ImmutableTable, ale jeśli zmienność nie jest wymagana, powinieneś użyć jej zamiast jednej zmiany - ImmutableTable (i dowolnej innej implementacji tabeli) nie ma metody columnKeyList(), ale tylko columnKeySet(), która robi to samo, ale jest wolniejsza dla ArrayTable. I oczywiście należy użyć ImmutableTable.Builder lub ImmutableTable.copyOf(Table).

+1

Skończyło się na użyciu tabeli i iteracji w każdym rzędzie, aby uzyskać mapę, która reprezentuje cały wiersz. – KJW

2

w pętli na wiele kluczy:

for (Object key : multimap.keys()) { ... } 

Można również pętla nad wpisów:

for (Map.Entry entry : multimap.entries()) { ... } 
+0

to jest miejsce, w którym jestem zdezorientowany, widziałem to w poprzednim pytaniu, ale nie byłem pewien jak to działa? Czy zwraca wszystkie wartości dla określonego klucza, czy zwraca każdą wartość powiązaną z kluczami? czy istnieje przykład tego w działaniu? – KJW

4

Można użyć jednej LinkedListMultimap lub LinkedHashMultimap.

Oba mają bardzo podobne zachowanie; jedną z głównych różnic jest to, że LinkedListMultimap pozwala na włożenie wielu kopii tej samej pary klucz-wartość, podczas gdy LinkedHashMultimap pozwala tylko na jedną.

Zobacz wyżej połączoną Javadoc, aby uzyskać więcej informacji.

+0

Nie jestem pewien co do pierwszego punktu. Próbowałem z uruchomionym przykładem, a kolejność iteracji przy użyciu dwóch multimetrów jest taka sama, używając kluczy, wartości, wpisów i asMap. – dawww

+1

@dawww: Ups, masz rację. Musiałem źle odczytać dokumentację. Usunę ten punkt, dzięki. :-) – ruakh

3

Nie jestem do końca jasne, co iteracja porządek znaczy OP ...

  • Set<K> keySet() prostu zwraca klucze.
  • zwraca klucze i powiązane z nimi wpisy, dzięki czemu można wykonać for (Map.Entry<K, Collection<V>> entry : asMap().entrySet()) w celu powtórzenia sekwencji kluczy i powiązanych z nimi kolekcji.
  • Collection<Map.Entry<K, V>> entries() umożliwia iterację wpisów, ale niekoniecznie grupowanie ich według klucza.

Jeśli chcesz rzeczy w celu wstawienia, użyj jednego z wstawiania zamówić Multimap wdrożeń - LinkedHashMultimap, ewentualnie LinkedListMultimap, ImmutableMultimap.