Szukam sposobu na przechowywanie par klucz-wartość. Potrzebuję wyszukiwania dwukierunkowego, ale jednocześnie muszę przechowywać wiele wartości dla tego samego klucza. Innymi słowy, coś jak BidiMap, ale dla każdego klucza może istnieć wiele wartości. Na przykład musi mieć możliwość przechowywania par takich jak: "s1" -> 1, "s2" -> 1, "s3" -> 2, i muszę mieć możliwość uzyskania wartości odwzorowanej na każdy klawisz, oraz dla każdej wartości uzyskaj wszystkie klucze z nią powiązane.Dwukierunkowa wielowartościowa mapa w języku Java
Odpowiedz
Potrzebujesz pomocy w relacjach między wieloma osobami? Najbliżej można uzyskać Guava 's Multimap
jak @Mechkov napisał - ale bardziej szczegółowo Multimap
połączenie z Multimaps.invertFrom
. "BiMultimap" nie jest jeszcze zaimplementowany, ale jest an issue, prosząc o tę funkcję w bibliotece Google Guava.
W tym momencie masz kilka opcji:
Jeśli twój „BiMultimap” będzie niezmienną stałą - użyj
Multimaps.invertFrom
iImmutableMultimap
/ImmutableListMultimap
/ImmutableSetMultimap
(każdy z theese trzech ma różne wartości zbiór przechowywanie). Niektóre kod (przykład wzięty z aplikacją I rozwijać, wykorzystujeEnum
s iSets.immutableEnumSet
):public class RolesAndServicesMapping { private static final ImmutableMultimap<Service, Authority> SERVICES_TO_ROLES_MAPPING = ImmutableMultimap.<Service, Authority>builder() .put(Service.SFP1, Authority.ROLE_PREMIUM) .put(Service.SFP, Authority.ROLE_PREMIUM) .put(Service.SFE, Authority.ROLE_EXTRA) .put(Service.SF, Authority.ROLE_STANDARD) .put(Service.SK, Authority.ROLE_STANDARD) .put(Service.SFP1, Authority.ROLE_ADMIN) .put(Service.ADMIN, Authority.ROLE_ADMIN) .put(Service.NONE, Authority.ROLE_DENY) .build(); // Whole magic is here: private static final ImmutableMultimap<Authority, Service> ROLES_TO_SERVICES_MAPPING = SERVICES_TO_ROLES_MAPPING.inverse(); // before guava-11.0 it was: ImmutableMultimap.copyOf(Multimaps.invertFrom(SERVICES_TO_ROLES_MAPPING, HashMultimap.<Authority, Service>create())); public static ImmutableSet<Authority> getRoles(final Service service) { return Sets.immutableEnumSet(SERVICES_TO_ROLES_MAPPING.get(service)); } public static ImmutableSet<Service> getServices(final Authority role) { return Sets.immutableEnumSet(ROLES_TO_SERVICES_MAPPING.get(role)); } }
Jeśli naprawdę chcesz, żeby Twój Multimap być modyfikowane, to będzie trudne do utrzymania zarówno K-> V i V-> K wariantów, chyba że będziesz modyfikować tylko
kToVMultimap
i zadzwonić pod numerinvertFrom
za każdym razem, gdy chcesz mieć jego odwróconą kopię (i uczynienie tej kopii niezmodyfikowaną, aby upewnić się, że przypadkiem nie zmieniszvToKMultimap
, co nie zaktualizowałobykToVMultimap
). Nie jest to optymalne, ale powinno być w tym przypadku.(Nie twoja sprawa prawdopodobnie wymienione jako bonus):
BiMap
interfejs i klasy wykonawcze ma.inverse()
metodę, która dajeBiMap<V, K>
widok zBiMap<K, V>
i sam pobiMap.inverse().inverse()
. Jeśli wspomniałem wcześniej, to prawdopodobnie będzie miało coś podobnego.(Edycja październik 2016) Można również użyć new graph API który będzie obecny w Guava 20:
Jako całość, wspólny.Wykres obsługuje wykresy z następujących odmian:
- skierowane wykresy
- nieukierunkowane wykresy
- węzłów i/lub krawędzie wartości powiązanych (wag, etykiety itd)
- wykresy do/nie pozwala siebie pętle
- wykresy do/nie pozwalają na równoległe krawędzie (wykresy z równoległymi krawędziami są czasami nazywane multigraphs)
- wykresy, których krawędzie są węzły/wstawiania uporządkowane, sortowane lub nieuporządkowane 0.123.
Nadzieja mam prawym
class A {
long id;
List<B> bs;
}
class B {
long id;
List<A> as;
}
Co jest złego w posiadanie dwóch mapach, kluczykowy> wartości, values-> klucze?
Myślałem, że zachowanie dwóch kopii tych samych danych będzie bardziej podatne na błędy. W każdym razie, po wszystkich kolekcjach, które oglądałem, zaczynam myśleć, że to najlepsze rozwiązanie. –
Po prostu utwórz opakowanie dla map, które je zsynchronizują. – Stefan
Nie podoba mi się podejście potwierdzone tą odpowiedzią. Jest wiele rzeczy, które mogą być z tym nie tak, włącznie z możliwością ponownego odkrywania koła, pisania własnych błędów po drodze, bezpieczeństwa wątków itp. – bacar
Google Guava MultiMap implementacja jest tym, czego używam do tych celów.
Map<Key Collection<Values>>
gdzie Kolekcja może być na przykład ArrayList. Pozwala na mapowanie wielu wartości przechowywanych w kolekcji na klucz. Mam nadzieję, że to pomoże!
Nie dwukierunkowe. – Stefan
Mam nadzieję, że za pomocą MultivaluedMap rozwiązuje problem. Proszę znaleźć dokumentację z wyroczni poniżej link.
http://docs.oracle.com/javaee/6/api/javax/ws/rs/core/MultivaluedMap.html
To jest interfejs. Czy są jakieś implementacje? – amoebe
Korzystanie z Google Guava możemy napisać prymitywną BiMulitMap jak poniżej.
import java.util.Collection;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
public class BiMultiMap<K,V> {
Multimap<K, V> keyToValue = ArrayListMultimap.create();
Multimap<V, K> valueToKey = ArrayListMultimap.create();
public void putForce(K key, V value) {
keyToValue.put(key, value);
valueToKey.put(value, key);
}
public void put(K key, V value) {
Collection<V> oldValue = keyToValue.get(key);
if (oldValue.contains(value) == false) {
keyToValue.put(key, value);
valueToKey.put(value, key);
}
}
public Collection<V> getValue(K key) {
return keyToValue.get(key);
}
public Collection<K> getKey(V value) {
return valueToKey.get(value);
}
@Override
public String toString() {
return "BiMultiMap [keyToValue=" + keyToValue + ", valueToKey=" + valueToKey + "]";
}
}
Mam nadzieję, że pomoże to w niektórych podstawowych potrzebach dwukierunkowej wieloplanowej mapy. Zauważ, że K i V muszą implementować hascode i jest to metoda równa
Mówisz o potrzebie posiadania wielu wartości na klucz, ale w twoim przykładzie nie masz klucza z wieloma wartościami, ale jedną wartość z dwoma kluczami. Powinieneś to wyjaśnić. Jeśli twój przykład pasuje do twojego pytania, dostaniesz lepsze odpowiedzi ;-) – pushy
http://www.jguru.com/faq/view.jsp?EID=1317828 tutaj możesz dowiedzieć się jak stworzyć multimap – maks
@pushy, ten sam problem, jeśli odwrócę mapę i zachowam liczby całkowite jako klucze zamiast wartości, otrzymuję mapowanie jeden-do-wielu. W każdym razie, dzięki za poprawkę. :) –