Gibt es eine Möglichkeit, eine Java HashMap wie diese zu initialisieren?:
Map<String,String> test =
new HashMap<String, String>{"test":"test","test":"test"};
Was wäre die richtige Syntax? Ich habe dazu nichts gefunden. Ist das möglich? Ich suche nach dem kürzesten / schnellsten Weg, um einige "endgültige / statische" Werte in eine Karte einzufügen, die sich nie ändern und die beim Erstellen der Karte im Voraus bekannt sind.
Antworten:
Alle Versionen
Für den Fall, dass Sie nur einen einzigen Eintrag benötigen: Es gibt
Collections.singletonMap("key", "value")
.Für Java Version 9 oder höher:
Ja, das ist jetzt möglich. In Java 9 wurden einige Factory-Methoden hinzugefügt, die das Erstellen von Karten vereinfachen:
Im obigen Beispiel sind beide
test
undtest2
gleich, nur mit unterschiedlichen Ausdrucksformen der Karte. DieMap.of
Methode ist für bis zu zehn Elemente in der Karte definiert, während dieMap.ofEntries
Methode keine solche Begrenzung hat.Beachten Sie, dass in diesem Fall die resultierende Karte eine unveränderliche Karte ist. Wenn Sie möchten, dass die Karte veränderbar ist, können Sie sie erneut kopieren, z
mutableMap = new HashMap<>(Map.of("a", "b"));
(Siehe auch JEP 269 und Javadoc )
Für bis zu Java Version 8:
Nein, Sie müssen alle Elemente manuell hinzufügen. Sie können einen Initialisierer in einer anonymen Unterklasse verwenden, um die Syntax etwas zu verkürzen:
In einigen Fällen kann die anonyme Unterklasse jedoch zu unerwünschtem Verhalten führen. Dies beinhaltet zum Beispiel:
Wenn Sie eine Funktion zur Initialisierung verwenden, können Sie auch eine Karte in einem Initialisierer erstellen, aber böse Nebenwirkungen vermeiden:
quelle
Collections.singletonMap()
:)entry
dokumentiert?Dies ist eine Möglichkeit.
Sie sollten jedoch vorsichtig sein und sicherstellen, dass Sie den obigen Code verstehen (es wird eine neue Klasse erstellt, die von HashMap erbt). Lesen Sie daher hier mehr: http://www.c2.com/cgi/wiki?DoubleBraceInitialization , oder verwenden Sie einfach Guava:
quelle
Wenn Sie Bibliotheken von Drittanbietern zulassen, können Sie die ImmutableMap von Guava verwenden , um eine wörtliche Kürze zu erreichen:
Dies funktioniert für bis zu 5 Schlüssel / Wert-Paare , andernfalls können Sie den Builder verwenden :
quelle
Es gibt keinen direkten Weg, dies zu tun - Java hat keine Map-Literale (noch - ich denke, sie wurden für Java 8 vorgeschlagen).
Manche Leute mögen das:
Dadurch wird eine anonyme Unterklasse von HashMap erstellt, deren Instanzinitialisierer diese Werte setzt. (Übrigens kann eine Karte nicht doppelt so viel Wert enthalten, Ihr zweiter Put überschreibt den ersten. Für die nächsten Beispiele verwende ich unterschiedliche Werte.)
Der normale Weg wäre folgender (für eine lokale Variable):
Wenn Ihre
test
Map eine Instanzvariable ist, fügen Sie die Initialisierung in einen Konstruktor oder Instanzinitialisierer ein:Wenn Ihre
test
Map eine Klassenvariable ist, fügen Sie die Initialisierung in einen statischen Initialisierer ein:Wenn Sie möchten, dass sich Ihre Karte niemals ändert, sollten Sie Ihre Karte nach der Initialisierung umschließen
Collections.unmodifiableMap(...)
. Sie können dies auch in einem statischen Initialisierer tun:(Ich bin mir nicht sicher, ob du jetzt das
test
Finale schaffen kannst ... probiere es aus und berichte hier.)quelle
quelle
HashMap
dieser Unterklasse fest. Dies kann nur funktionieren, wenn Sie sie tatsächlich bereitstellen. (Mit einer neuen (leeren) HashMap sind die Typargumente nicht relevant.)Eine Alternative mit einfachen Java 7-Klassen und -Varargs: Erstellen Sie eine Klasse
HashMapBuilder
mit dieser Methode:Verwenden Sie die Methode wie folgt:
quelle
tl; dr
Verwenden Sie
Map.of…
Methoden in Java 9 und höher.Map.of
Java 9 hat eine Reihe
Map.of
statischer Methoden hinzugefügt , um genau das zu tun, was Sie wollen: Instanziieren Sie eine unveränderlicheMap
Methode mithilfe der Literal-Syntax .Die Karte (eine Sammlung von Einträgen) ist unveränderlich, sodass Sie nach dem Instanziieren keine Einträge hinzufügen oder entfernen können. Auch der Schlüssel und der Wert jedes Eintrags sind unveränderlich, können nicht geändert werden. Weitere Regeln finden Sie im Javadoc , z. B. keine zulässigen NULL-Werte, keine zulässigen doppelten Schlüssel und die willkürliche Reihenfolge der Zuordnungen.
Schauen wir uns diese Methoden an und verwenden einige Beispieldaten für eine Karte des Wochentags für eine Person, von der wir erwarten, dass sie an diesem Tag arbeitet.
Map.of()
Map.of
erstellt eine leereMap
. Nicht änderbar, daher können Sie keine Einträge hinzufügen. Hier ist ein Beispiel für eine solche Karte, leer ohne Einträge.Map.of( … )
Map.of( k , v , k , v , …)
Es gibt verschiedene Methoden, die 1 bis 10 Schlüssel-Wert-Paare annehmen. Hier ist ein Beispiel für zwei Einträge.Map.ofEntries( … )
Map.ofEntries( Map.Entry , … )
Nimmt eine beliebige Anzahl von Objekten, die dieMap.Entry
Schnittstelle implementieren . Java bündelt zwei Klassen, die diese Schnittstelle implementieren, eine veränderlich, die andere unveränderlich:AbstractMap.SimpleEntry
,AbstractMap.SimpleImmutableEntry
. Wir müssen jedoch keine konkrete Klasse angeben. Wir müssen lediglich dieMap.entry( k , v )
Methode aufrufen , unseren Schlüssel und unseren Wert übergeben und erhalten ein Objekt einer Klasse zurück, die eineMap.Entry
Schnittstelle implementiert .Map.copyOf
Java 10 hat die Methode hinzugefügt
Map.copyOf
. Übergeben Sie eine vorhandene Karte und erhalten Sie eine unveränderliche Kopie dieser Karte zurück.Anmerkungen
Beachten Sie, dass die Iterator Reihenfolge der Karten hergestellt via
Map.of
ist nicht garantiert. Die Einträge haben eine beliebige Reihenfolge. Schreiben Sie keinen Code basierend auf der angezeigten Reihenfolge, da die Dokumentation warnt, dass sich die Bestellung ändern kann.Beachten Sie, dass alle diese
Map.of…
Methoden eine RückkehrMap
von einer nicht spezifizierten Klasse . Die zugrunde liegende konkrete Klasse kann sogar von einer Java-Version zur anderen variieren. Diese Anonymität ermöglicht es Java, aus verschiedenen Implementierungen auszuwählen, je nachdem, was optimal zu Ihren Daten passt. Wenn Ihre Schlüssel beispielsweise aus einer Enumeration stammen , verwendet Java möglicherweise einEnumMap
Under-the-Cover.quelle
Möglicherweise können Sie Ihre eigene
Map.of
Methode (die nur in Java 9 und höher verfügbar ist) auf zwei einfache Arten erstellenMachen Sie es mit einer festgelegten Anzahl von Parametern
Beispiel
Machen Sie es mit einer Liste
Sie können dies auch mithilfe einer Liste erstellen, anstatt viele Methoden für einen bestimmten Parametersatz zu erstellen.
Beispiel
Hinweis Es wird nicht empfohlen, dies für alles zu verwenden, da dies jedes Mal eine anonyme Klasse ergibt, wenn Sie dies verwenden.
quelle
JAVA 8
In Plain Java 8 haben Sie auch die Möglichkeit
Streams/Collectors
, die Arbeit zu erledigen.Dies hat den Vorteil, dass keine anonyme Klasse erstellt wird.
Beachten Sie, dass die Importe sind:
Wie in anderen Antworten erwähnt, haben Sie ab Java 9 natürlich einfachere Möglichkeiten, dasselbe zu tun.
quelle
Leider ist die Verwendung von varargs, wenn der Typ der Schlüssel und Werte nicht identisch ist, nicht sehr sinnvoll, da Sie die Typensicherheit
Object...
vollständig verwenden und verlieren müssten . Wenn Sie immer zB a erstellen möchtenMap<String, String>
, natürlich atoMap(String... args)
wäre möglich, aber nicht sehr hübsch, da es einfach wäre, Schlüssel und Werte zu verwechseln, und eine ungerade Anzahl von Argumenten ungültig wäre.Sie können eine Unterklasse von HashMap erstellen, die eine verkettbare Methode wie hat
und benutze es gerne
new ChainableMap<String, Object>().set("a", 1).set("b", "foo")
Ein anderer Ansatz besteht darin, das allgemeine Builder-Muster zu verwenden:
und benutze es gerne
new MapBuilder<String, Object>().put("a", 1).put("b", "foo").build();
Die Lösung, die ich ab und zu verwendet habe, verwendet jedoch varargs und die
Pair
Klasse:Map<String, Object> map = Maps.of(Pair.create("a", 1), Pair.create("b", "foo");
Die Ausführlichkeit von
Pair.create()
stört mich ein bisschen, aber das funktioniert ganz gut. Wenn Ihnen statische Importe nichts ausmachen, können Sie natürlich einen Helfer erstellen:Map<String, Object> map = Maps.of(p("a", 1), p("b", "foo");
(Anstelle der
Pair
Verwendung könnte man sich vorstellenMap.Entry
, aber da es sich um eine Schnittstelle handelt, ist eine implementierende Klasse und / oder eine Helfer-Factory-Methode erforderlich. Sie ist auch nicht unveränderlich und enthält andere Logik, die für diese Aufgabe nicht nützlich ist.)quelle
Sie können Streams in Java 8 verwenden (dies ist ein Beispiel für Set):
Ref: https://www.baeldung.com/java-double-brace-initialization
quelle
Wenn Sie nur ein Schlüssel-Wert-Paar platzieren müssen, können Sie Collections.singletonMap (Schlüssel, Wert) verwenden.
quelle