Czy istnieje jakiś sposób na zainicjowanie Java HashMap w ten sposób ?:
Map<String,String> test =
new HashMap<String, String>{"test":"test","test":"test"};
Jaka byłaby poprawna składnia? Nie znalazłem nic na ten temat. czy to możliwe? Szukam najkrótszego / najszybszego sposobu umieszczenia niektórych wartości „końcowych / statycznych” na mapie, które nigdy się nie zmieniają i są znane z góry podczas tworzenia mapy.
Odpowiedzi:
Wszystkie wersje
Jeśli potrzebujesz tylko jednego wpisu: istnieje
Collections.singletonMap("key", "value")
.W przypadku wersji Java 9 lub nowszej:
Tak, jest to teraz możliwe. W Javie 9 dodano kilka fabrycznych metod, które upraszczają tworzenie map:
W powyższym przykładzie oba
test
itest2
będzie taki sam, tylko z różnych sposobów wyrażania mapę.Map.of
Metoda jest zdefiniowana przez okres do dziesięciu elementów mapy, podczas gdyMap.ofEntries
metoda nie będzie miał takiego limitu.Zauważ, że w tym przypadku wynikowa mapa będzie mapą niezmienną. Jeśli chcesz, aby mapa była zmienna, możesz skopiować ją ponownie, np. Używając
mutableMap = new HashMap<>(Map.of("a", "b"));
(Zobacz także JEP 269 i Javadoc )
Dla wersji Java 8:
Nie, będziesz musiał ręcznie dodać wszystkie elementy. Możesz użyć inicjalizatora w anonimowej podklasie, aby skrócić składnię:
Jednak w niektórych przypadkach anonimowa podklasa może powodować niepożądane zachowanie. Obejmuje to na przykład:
Użycie funkcji do inicjalizacji pozwoli ci również wygenerować mapę w inicjalizatorze, ale pozwoli uniknąć nieprzyjemnych efektów ubocznych:
źródło
Collections.singletonMap()
:)entry
udokumentowane Java 9 ?To jest jeden sposób.
Należy jednak zachować ostrożność i upewnić się, że rozumiesz powyższy kod (tworzy on nową klasę, która dziedziczy po HashMap). Dlatego powinieneś przeczytać więcej tutaj: http://www.c2.com/cgi/wiki?DoubleBraceInitialization , lub po prostu użyj Guava:
źródło
Jeśli pozwolisz bibliotekami 3rd party, można użyć Guava „s ImmutableMap osiągnąć podobny dosłowny zwięzłości:
Działa to dla maksymalnie 5 par klucz / wartość , w przeciwnym razie możesz użyć jego konstruktora :
źródło
Nie ma na to bezpośredniego sposobu - Java nie ma literałów mapy (jeszcze - myślę, że zostały one zaproponowane dla Java 8).
Niektórzy lubią to:
To tworzy anonimową podklasę HashMap, której inicjator instancji umieszcza te wartości. (Nawiasem mówiąc, mapa nie może zawierać dwa razy tej samej wartości, twoje drugie wstawienie zastąpi pierwszą. Użyję różnych wartości dla następnych przykładów.)
Normalny sposób byłby następujący (dla zmiennej lokalnej):
Jeśli twoja
test
mapa jest zmienną instancji, umieść inicjalizację w konstruktorze lub inicjatorze instancji:Jeśli twoja
test
mapa jest zmienną klasową, umieść inicjalizację w inicjalizatorze statycznym:Jeśli chcesz, aby twoja mapa nigdy się nie zmieniała, po inicjalizacji powinieneś ją owinąć
Collections.unmodifiableMap(...)
. Możesz to zrobić również w statycznym inicjalizatorze:(Nie jestem pewien, czy możesz teraz dokonać
test
ostatecznego ... wypróbuj go i zgłoś się tutaj).źródło
źródło
HashMap
w tej podklasie. Może to działać tylko wtedy, gdy faktycznie je udostępnisz. (W nowej (pustej) HashMap argumenty typu nie są istotne.)Alternatywą jest użycie klas Java 7 i varargs: utwórz klasę za
HashMapBuilder
pomocą tej metody:Użyj następującej metody:
źródło
tl; dr
Użyj
Map.of…
metod w Javie 9 i nowszych.Map.of
Java 9 dodała szereg
Map.of
statycznych metod, aby zrobić dokładnie to, co chcesz: utworzyć instancję niezmiennegoMap
za pomocą składni literalnej .Mapa (zbiór wpisów) jest niezmienna, więc nie można dodawać ani usuwać wpisów po utworzeniu wystąpienia. Ponadto klucz i wartość każdego wpisu są niezmienne, nie można ich zmienić. Zobacz Javadoc, aby poznać inne reguły, takie jak niedozwolone wartości NULL, niedozwolone duplikaty kluczy, a kolejność odwzorowań jest dowolna.
Spójrzmy na te metody, wykorzystując przykładowe dane do mapy dnia tygodnia dla osoby, która, jak się spodziewamy, będzie pracować tego dnia.
Map.of()
Map.of
tworzy pusteMap
. Niemodyfikowalna, więc nie można dodawać wpisów. Oto przykład takiej mapy, pustej bez wpisów.Map.of( … )
Map.of( k , v , k , v , …)
jest kilka metod, które przyjmują od 1 do 10 par klucz-wartość. Oto przykład dwóch wpisów.Map.ofEntries( … )
Map.ofEntries( Map.Entry , … )
pobiera dowolną liczbę obiektów implementującychMap.Entry
interfejs. Java łączy dwie klasy implementujące ten interfejs, jedną zmienną, drugą niezmienną:AbstractMap.SimpleEntry
,AbstractMap.SimpleImmutableEntry
. Ale nie musimy określać konkretnej klasy. Musimy tylko wywołaćMap.entry( k , v )
metodę, przekazać nasz klucz i naszą wartość, i otrzymamy obiektMap.Entry
interfejsu implementacyjnego klasy .Map.copyOf
Java 10 dodała tę metodę
Map.copyOf
. Minąć istniejącą mapę, odzyskać niezmienną kopię tej mapy.Notatki
Zauważ, że kolejność iterator map produkowane przez
Map.of
się nie jest gwarantowana. Wpisy mają dowolny porządek. Nie pisz kodu w oparciu o widziane zamówienie, ponieważ dokumentacja ostrzega, że zamówienie może ulec zmianie.Należy pamiętać, że wszystkie te
Map.of…
metody zwracająMap
z nieokreślonej klasy . Podstawowa konkretna klasa może nawet różnić się w zależności od wersji Java. Ta anonimowość pozwala Java wybierać spośród różnych implementacji, niezależnie od tego, które optymalnie pasują do konkretnych danych. Na przykład, jeśli klucze pochodzą z wyliczenia , Java może użyćEnumMap
pod okładkami.źródło
Możesz łatwo stworzyć własną
Map.of
metodę (która jest dostępna tylko w Javie 9 i wyższych) na 2 proste sposobyZrób to z określoną ilością parametrów
Przykład
Zrób to za pomocą listy
Możesz to zrobić za pomocą listy, zamiast tworzyć wiele metod dla określonego zestawu parametrów.
Przykład
Uwaga Nie zaleca się używania tego do wszystkiego, ponieważ tworzy to anonimową klasę za każdym razem, gdy z niej korzystasz.
źródło
JAVA 8
W zwykłym java 8 masz również możliwość skorzystania
Streams/Collectors
z tego zadania.Ma to tę zaletę, że nie tworzy klasy Anonimowej.
Pamiętaj, że importowane są:
Oczywiście, jak zauważono w innych odpowiedziach, w Javie 9 i nowszej masz prostsze sposoby robienia tego samego.
źródło
Niestety używanie varargs, jeśli typ kluczy i wartości nie są takie same, nie jest zbyt rozsądne, ponieważ trzeba by
Object...
całkowicie użyć i utracić bezpieczeństwo typu. Jeśli zawsze chcesz stworzyć np. AMap<String, String>
, oczywiścietoMap(String... args)
byłoby to możliwe, ale niezbyt ładne, ponieważ łatwo byłoby mieszać klucze i wartości, a nieparzysta liczba argumentów byłaby niepoprawna.Możesz utworzyć podklasę HashMap, która ma metodę łańcuchową taką jak
i używaj go jak
new ChainableMap<String, Object>().set("a", 1).set("b", "foo")
Innym podejściem jest użycie wspólnego wzorca konstruktora:
i używaj go jak
new MapBuilder<String, Object>().put("a", 1).put("b", "foo").build();
Jednak rozwiązanie, z którego korzystałem od czasu do czasu, wykorzystuje varargs i
Pair
klasę:Map<String, Object> map = Maps.of(Pair.create("a", 1), Pair.create("b", "foo");
Gadatliwość
Pair.create()
trochę mi przeszkadza, ale to działa całkiem dobrze. Jeśli nie masz nic przeciwko importowi statycznemu, możesz oczywiście utworzyć pomocnika:Map<String, Object> map = Maps.of(p("a", 1), p("b", "foo");
(Zamiast tego
Pair
można sobie wyobrazić użycieMap.Entry
, ale ponieważ jest to interfejs, wymaga klasy implementacyjnej i / lub metody fabryki pomocników. Nie jest również niezmienny i zawiera inną logikę nieprzydatną do tego zadania).źródło
Możesz używać strumieni w Javie 8 (jest to przykład Seta):
Patrz: https://www.baeldung.com/java-double-brace-initialization
źródło
Jeśli potrzebujesz umieścić tylko jedną parę klucz-wartość, możesz użyć Collections.singletonMap (klucz, wartość);
źródło