web-dev-qa-db-ger.com

Wie initialisiere ich eine HashMap direkt (im wahrsten Sinne des Wortes)?

Gibt es eine Möglichkeit, eine Java HashMap wie folgt 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.

937
jens

Für Java Version 9 oder höher:

Ja, das ist jetzt möglich. In Java 9 wurden einige Factory-Methoden hinzugefügt, die die Erstellung von Maps vereinfachen:

// this works for up to 10 elements:
Map<String, String> test1 = Map.of(
    "a", "b",
    "c", "d"
);

// this works for any number of elements:
Map<String, String> test2 = Map.ofEntries(
    entry("a", "b"),
    entry("c", "d")
);

Im obigen Beispiel sind sowohl test als auch test2 gleich, nur mit unterschiedlichen Arten, die Map auszudrücken. Die Map.of -Methode ist für bis zu zehn Elemente in der Map definiert, während die Map.ofEntries -Methode keine solche Begrenzung hat.

Beachten Sie, dass die resultierende Karte in diesem Fall eine unveränderliche Karte ist. Wenn Sie möchten, dass die Karte veränderbar ist, können Sie sie erneut kopieren, z. mit 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 ein wenig zu verkürzen:

Map<String, String> myMap = new HashMap<>() {{
        put("a", "b");
        put("c", "d");
    }};

In einigen Fällen kann die anonyme Unterklasse jedoch zu unerwünschtem Verhalten führen. Dies beinhaltet zum Beispiel:

  • Es wird eine zusätzliche Klasse generiert, die den Speicherverbrauch, den Speicherplatzverbrauch und die Startzeit erhöht
  • Bei einer nicht statischen Methode: Sie enthält einen Verweis auf das Objekt, auf das die Erstellungsmethode angewendet wurde. Das heißt, das Objekt der äußeren Klasse kann nicht über den Müll gesammelt werden, solange auf das erstellte Kartenobjekt noch verwiesen wird, wodurch zusätzlicher Speicher blockiert wird

Die Verwendung einer Funktion zur Initialisierung ermöglicht es Ihnen auch, eine Karte in einem Initialisierer zu generieren, vermeidet jedoch böse Nebenwirkungen:

Map<String, String> myMap = createMap();

private static Map<String, String> createMap() {
    Map<String,String> myMap = new HashMap<String,String>();
    myMap.put("a", "b");
    myMap.put("c", "d");
    return myMap;
}
1136
yankee

Das ist eine Möglichkeit.

HashMap<String, String> h = new HashMap<String, String>() {{
    put("a","b");
}};

Sie sollten jedoch vorsichtig sein und sicherstellen, dass Sie den obigen Code verstehen (er erstellt eine neue Klasse, die von HashMap erbt). Lesen Sie daher hier mehr: http://www.c2.com/cgi/wiki?DoubleBraceInitialization oder verwenden Sie einfach Guava:

Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
1010
gregory561

Wenn Sie Drittanbieter-Bibliotheken zulassen, können Sie Guava 's ImmutableMap verwenden, um eine buchstäbliche Kürze zu erzielen:

Map<String, String> test = ImmutableMap.of("k1", "v1", "k2", "v2");

Dies funktioniert für bis zu 5 Schlüssel/Wert-Paare , ansonsten können Sie sein Builder verwenden:

Map<String, String> test = ImmutableMap.<String, String>builder()
    .put("k1", "v1")
    .put("k2", "v2")
    ...
    .build();


  • beachten Sie, dass die ImmutableMap -Implementierung von Guava von der HashMap -Implementierung von Java abweicht (insbesondere ist sie unveränderlich und lässt keine Nullschlüssel/-werte zu)
  • weitere Informationen finden Sie in Guavas Benutzerhandbuch im Artikel nveränderliche Sammlungstypen
327
Jens Hoffmann

Es gibt keine direkte Möglichkeit, dies zu tun - Java hat keine Map-Literale (noch - ich denke, sie wurden für Java 8 vorgeschlagen).

Einige Leute mögen das:

Map<String,String> test = new HashMap<String, String>(){{
       put("test","test"); put("test","test");}};

Dadurch wird eine anonyme Unterklasse von HashMap erstellt, deren Instanzinitialisierer diese Werte festlegt. (Übrigens kann eine Map nicht zweimal den gleichen Wert enthalten, Ihr zweiter Put überschreibt den ersten. Für die nächsten Beispiele verwende ich andere Werte.)

Der normale Weg wäre (für eine lokale Variable):

Map<String,String> test = new HashMap<String, String>();
test.put("test","test");
test.put("test1","test2");

Wenn Ihre test-Map eine Instanzvariable ist, fügen Sie die Initialisierung in einen Konstruktor oder einen Instanzinitialisierer ein:

Map<String,String> test = new HashMap<String, String>();
{
    test.put("test","test");
    test.put("test1","test2");
}

Wenn Ihre test Map eine Klassenvariable ist, platzieren Sie die Initialisierung in einem statischen Initialisierer:

static Map<String,String> test = new HashMap<String, String>();
static {
    test.put("test","test");
    test.put("test1","test2");
}

Wenn Sie möchten, dass sich Ihre Map niemals ändert, sollten Sie Ihre Map nach der Initialisierung mit Collections.unmodifiableMap(...) umschließen. Sie können dies auch in einem statischen Initialisierer tun:

static Map<String,String> test;
{
    Map<String,String> temp = new HashMap<String, String>();
    temp.put("test","test");
    temp.put("test1","test2");
    test = Collections.unmodifiableMap(temp);
}

(Ich bin nicht sicher, ob Sie jetzt test final machen können ... probieren Sie es aus und berichten Sie hier.)

103
Paŭlo Ebermann
Map<String,String> test = new HashMap<String, String>()
{
    {
        put(key1, value1);
        put(key2, value2);
    }
};
61
Shaggy Frog

Eine Alternative mit einfachen Java 7-Klassen und -Varargen: Erstellen Sie eine Klasse HashMapBuilder mit dieser Methode:

public static HashMap<String, String> build(String... data){
    HashMap<String, String> result = new HashMap<String, String>();

    if(data.length % 2 != 0) 
        throw new IllegalArgumentException("Odd number of arguments");      

    String key = null;
    Integer step = -1;

    for(String value : data){
        step++;
        switch(step % 2){
        case 0: 
            if(value == null)
                throw new IllegalArgumentException("Null key value"); 
            key = value;
            continue;
        case 1:             
            result.put(key, value);
            break;
        }
    }

    return result;
}

Verwenden Sie die Methode wie folgt:

HashMap<String,String> data = HashMapBuilder.build("key1","value1","key2","value2");
42
Aerthel