Mam tablicę liczb całkowitych 2D. Chcę, aby zostały umieszczone w HashMap. Ale chcę uzyskać dostęp do elementów z HashMap w oparciu o indeks tablicy. Coś jak:
Dla A [2] [5], map.get(2,5)
która zwraca wartość skojarzoną z tym kluczem. Ale jak utworzyć mapę mieszania za pomocą pary kluczy? Lub ogólnie wiele kluczy: Map<((key1, key2,..,keyN), Value)
w taki sposób, że mogę uzyskać dostęp do elementu za pomocą get (klucz1, klucz2, ... kluczN).
EDYCJA: 3 lata po opublikowaniu pytania chcę dodać do niego trochę więcej
Znalazłem inny sposób NxN matrix
.
Indeksy tablicowe i
i j
można je przedstawić jako pojedynczy key
w następujący sposób:
int key = i * N + j;
//map.put(key, a[i][j]); // queue.add(key);
A indeksy można pobrać z tego key
w ten sposób:
int i = key / N;
int j = key % N;
Odpowiedzi:
Istnieje kilka opcji:
2 wymiary
Mapa map
Obiekt klucza opakowania
Wdrażanie
equals()
ihashCode()
jest tutaj kluczowe. Następnie po prostu użyj:i:
Table
z GuawyTable
używa mapy map poniżej.Wymiary N.
Zauważ, że
Key
klasa specjalna jest jedynym podejściem, które skaluje się do n-wymiarów. Możesz również rozważyć:ale to straszne z punktu widzenia wydajności, a także czytelności i poprawności (nie ma łatwego sposobu na wymuszenie rozmiaru listy).
Może spójrz na Scala, gdzie masz krotki i
case
klasy (zastępując całąKey
klasę jedną linijką).źródło
Map.Entry<K, V>
jako klucza?Map<Pair<Key1, Key2>, Value>
?hashCode()
można to również zaimplementować z pojedynczą linią jakoObjects.hash(x,y)
Kiedy tworzysz swój własny obiekt pary kluczy, powinieneś zmierzyć się z kilkoma rzeczami.
Po pierwsze, powinieneś być świadomy implementacji
hashCode()
iequals()
. Będziesz musiał to zrobić.Po drugie, podczas wdrażania
hashCode()
upewnij się, że rozumiesz, jak to działa. Podany przykład użytkownikajest właściwie jedną z najgorszych implementacji, jakie możesz zrobić. Powód jest prosty: masz dużo równych haszów! A
hashCode()
powinien zwrócić wartości int, które mają tendencję do być rzadki, wyjątkowy w najlepszym. Użyj czegoś takiego:Jest to szybkie i zwraca unikalne skróty dla kluczy od -2 ^ 16 do 2 ^ 16-1 (od -65536 do 65535). Pasuje to prawie do każdego przypadku. Bardzo rzadko jesteś poza tym zakresem.
Po trzecie, podczas implementacji
equals()
wiedz również, do czego służy i bądź świadomy tego, jak tworzysz klucze, ponieważ są one obiektami. Często robisz to niepotrzebnie, jeśli stwierdzenia powodują, że zawsze będziesz miał ten sam rezultat.Jeśli utworzysz klucze w ten sposób:
map.put(new Key(x,y),V);
nigdy nie będziesz porównywać referencji swoich kluczy. Ponieważ za każdym razem, gdy chcesz uzyskać dostęp do mapy, zrobisz coś takiegomap.get(new Key(x,y));
. Dlategoequals()
nie potrzebujesz takiego oświadczeniaif (this == obj)
. To się nigdy nie wydarzy.Zamiast
if (getClass() != obj.getClass())
wequals()
lepszym użyciuif (!(obj instanceof this))
. Będzie obowiązywać nawet dla podklas.Więc jedyne, co musisz porównać, to w rzeczywistości X i Y. Więc najlepsza
equals()
implementacja w tym przypadku to:Ostatecznie twoja kluczowa klasa wygląda tak:
Możesz podać swoje indeksy wymiarów
X
iY
poziom dostępu publicznego, ponieważ są one ostateczne i nie zawierają poufnych informacji. Nie jestem w 100% pewien, czyprivate
poziom dostępu działa poprawnie w każdym przypadku podczas przesyłaniaObject
do plikuKey
.Jeśli zastanawiasz się nad finałami, deklaruję wszystko jako ostateczne, którego wartość jest ustawiona na instancji i nigdy się nie zmienia - i dlatego jest stałą obiektową.
źródło
Nie możesz mieć mapy skrótów z wieloma kluczami, ale możesz mieć obiekt, który przyjmuje wiele parametrów jako klucz.
Utwórz obiekt o nazwie Index, który przyjmuje wartości x i y.
Następnie miej
HashMap<Index, Value>
swój wynik. :)źródło
hashCode
iequals
.Zaimplementowane we wspólnych kolekcjach MultiKeyMap
źródło
Dwie możliwości. Albo użyj łączonego klucza:
Lub mapa mapy:
źródło
hashCode
iequals
metodach.Użyj
Pair
jako kluczy doHashMap
. JDK nie ma pary, ale możesz skorzystać z biblioteki innej firmy, takiej jak http://commons.apache.org/lang, lub napisać własny typ pary.źródło
Utwórz klasę wartości, która będzie reprezentować Twój klucz złożony, na przykład:
dbając o to, aby zastąpić
equals()
ihashCode()
poprawnie. Jeśli wydaje się, że to dużo pracy, możesz rozważyć kilka gotowych ogólnych kontenerów, takich jakPair
między innymi dostarczone przez apache commons.Jest tu również wiele podobnych pytań , z innymi pomysłami, takimi jak użycie tabeli guawy , chociaż pozwala na to, aby klucze miały różne typy, co może być przesadą (w przypadku użycia pamięci i złożoności) w twoim przypadku, ponieważ rozumiem, że oba klucze są liczbami całkowitymi.
źródło
Jeśli są to dwie liczby całkowite, możesz wypróbować szybką i nieprzyjemną sztuczkę:
Map<String, ?>
używając klucza asi+"#"+j
.Jeśli klucz
i+"#"+j
jest taki sam jakj+"#"+i
trymin(i,j)+"#"+max(i,j)
.źródło
String
z zabawnymi konsekwencjami.i#j = j#i
przyi == j
takim użyciumin/max
sztuczki nie da się.5#5
i5#5
zamienione?5#3
mieć taki sam hash3#5
, wtedy używasz min / max, aby wymusić3#5
w tej kolejności.Możesz również użyć do tego implementacji stołu z guawy .
Tabela reprezentuje specjalną mapę, na której można określić dwa klucze w połączeniu w celu odniesienia się do jednej wartości. Jest to podobne do tworzenia mapy map.
źródło
Możesz stworzyć swój kluczowy obiekt mniej więcej tak:
public class MapKey {
}
Zaletą takiego rozwiązania jest to, że zawsze upewni się, że uwzględniasz również wszystkie scenariusze Równości.
UWAGA : Twoje key1 i key2 powinny być niezmienne. Tylko wtedy będziesz w stanie zbudować stabilny kluczowy Obiekt.
źródło
możemy stworzyć klasę przekazującą więcej niż jeden klucz lub wartość, a obiekt tej klasy może być użyty jako parametr w mapie.
źródło
Możesz go pobrać z poniższego linku: https://github.com/VVS279/DoubleKeyHashMap/blob/master/src/com/virtualMark/doubleKeyHashMap/DoubleKeyHashMap.java
https://github.com/VVS279/DoubleKeyHashMap
Możesz użyć podwójnego klucza: wartość hashmap,
źródło