Hinzufügen mehrerer Einträge zu einer HashMap gleichzeitig in einer Anweisung


138

Ich muss eine konstante HashMap initialisieren und möchte dies in einer einzeiligen Anweisung tun. So etwas vermeiden:

  hashMap.put("One", new Integer(1)); // adding value into HashMap
  hashMap.put("Two", new Integer(2));      
  hashMap.put("Three", new Integer(3));

ähnlich wie in Ziel C:

[NSDictionary dictionaryWithObjectsAndKeys:
@"w",[NSNumber numberWithInt:1],
@"K",[NSNumber numberWithInt:2],
@"e",[NSNumber numberWithInt:4],
@"z",[NSNumber numberWithInt:5],
@"l",[NSNumber numberWithInt:6],
nil] 

Ich habe kein Beispiel gefunden, das zeigt, wie man das macht, nachdem ich so viele angeschaut habe.

Antworten:


258

Du kannst das:

Map<String, Integer> hashMap = new HashMap<String, Integer>()
{{
     put("One", 1);
     put("Two", 2);
     put("Three", 3);
}};

11
@ user387184 Ja, sie nennen es "Double Brace Initialisierer". Siehe dieses Thema: stackoverflow.com/questions/924285/…
Eng.Fouad

2
Ich habe es einfach in meinen Code eingefügt und erhalte diese Warnung / Meldung in der Zeile: "Die serialisierbare Klasse deklariert kein statisches endgültiges serialVersionUID-Feld vom Typ long". Kann ich das einfach ignorieren? was bedeutet das? Danke
user387184

31
Sie sollten diese Methode nicht verwenden. Es wird für jedes Mal, wenn Sie es verwenden, eine neue Klasse erstellt, die eine viel schlechtere Leistung aufweist als das einfache Erstellen einer Karte. Siehe stackoverflow.com/questions/924285/…
Timo Türschmann

7
Der Grund, warum ich dies abgelehnt habe, ist, dass nicht erklärt wurde, dass dadurch für jedes Mal, wenn Sie es verwenden, eine neue Klasse erstellt wird. Ich denke, die Leute sollten sich der Kompromisse bewusst sein, die sich daraus ergeben.
Idungotnosn

6
@ TimoTürschmann Scheint, dass wenn ich jemals eine statische Initialisierung einer Karte wie dieser benötigt hätte, diese auch statisch wäre, wodurch jedes Mal, wenn Sie sie verwenden, eine Leistungsminderung beseitigt würde - Sie hätten diese Strafe einmal. Ich kann kein anderes Mal sehen, dass man diese Art der Initialisierung möchte, ohne dass die Variable statisch ist (z. B. würde jemand dies jemals in einer Schleife verwenden?). Ich kann mich jedoch irren, Programmierer sind erfinderisch.
Chris Cirefice

65

Sie können die ImmutableMap von Google Guava verwenden. Dies funktioniert so lange, wie Sie die Karte später nicht mehr ändern möchten (Sie können .put () auf der Karte nicht aufrufen, nachdem Sie sie mit dieser Methode erstellt haben):

import com.google.common.collect.ImmutableMap;

// For up to five entries, use .of()
Map<String, Integer> littleMap = ImmutableMap.of(
    "One", Integer.valueOf(1),
    "Two", Integer.valueOf(2),
    "Three", Integer.valueOf(3)
);

// For more than five entries, use .builder()
Map<String, Integer> bigMap = ImmutableMap.<String, Integer>builder()
    .put("One", Integer.valueOf(1))
    .put("Two", Integer.valueOf(2))
    .put("Three", Integer.valueOf(3))
    .put("Four", Integer.valueOf(4))
    .put("Five", Integer.valueOf(5))
    .put("Six", Integer.valueOf(6))
    .build();

Siehe auch: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableMap.html

Eine etwas verwandte Frage: Problemumgehung von ImmutableMap.of () für HashMap in Maps?


Guave ist riesig, ich würde es nicht für meine Android-App verwenden, es sei denn, es ist absolut notwendig
Ericic

4
Beachten Sie, dass ImmutableMapkeine nullSchlüssel oder Werte akzeptiert werden.
Vadzim

Mit @ericn ProGuard können Sie alle Teile einer Bibliothek ausschließen, die Sie nicht verwenden.
dimo414

55

Seit Java 9 ist es möglich Map.of(...), wie folgt zu verwenden :

Map<String, Integer> immutableMap = Map.of("One", 1, 
                                           "Two", 2, 
                                           "Three", 3);

Diese Karte ist unveränderlich. Wenn die Karte veränderbar sein soll, müssen Sie Folgendes hinzufügen:

Map<String, Integer> hashMap = new HashMap<>(immutableMap);

Wenn Sie Java 9 nicht verwenden können, müssen Sie selbst eine ähnliche Hilfsmethode schreiben oder eine Bibliothek eines Drittanbieters (wie Guava ) verwenden, um diese Funktionalität für Sie hinzuzufügen.


Nach dem Hinzufügen von 10 Einträgen wird der seltsame Fehler "Methode kann nicht aufgelöst werden" ausgegeben. Ist dieser Fehler bei dieser Methode?
Vikramvi

2
@vikramvi ja Wenn Sie sich die Dokumentation ansehen, werden Map.ofnur bis zu 10 Einträge gemacht, da es ziemlich mühsam ist
jolivier

8

Java hat kein Kartenliteral, daher gibt es keine gute Möglichkeit, genau das zu tun, was Sie verlangen.

Wenn Sie diese Art von Syntax benötigen, sollten Sie Groovy in Betracht ziehen, das Java-kompatibel ist und Folgendes ermöglicht:

def map = [name:"Gromit", likes:"cheese", id:1234]

8

In Maps wurden auch Factory-Methoden in Java 9 hinzugefügt. Für bis zu 10 Einträge haben Maps Konstruktoren überladen, die Schlüssel- und Wertepaare annehmen. Zum Beispiel könnten wir eine Karte verschiedener Städte und ihrer Bevölkerung (laut Google im Oktober 2016) wie folgt erstellen:

Map<String, Integer> cities = Map.of("Brussels", 1_139000, "Cardiff", 341_000);

Der var-args-Fall für Map ist etwas schwieriger. Sie müssen sowohl Schlüssel als auch Werte haben, aber in Java können Methoden nicht zwei var-args-Parameter haben. Der allgemeine Fall wird also behandelt, indem eine var-args-Methode für Map.Entry<K, V>Objekte verwendet und eine statische entry()Methode hinzugefügt wird, die sie erstellt. Beispielsweise:

Map<String, Integer> cities = Map.ofEntries(
    entry("Brussels", 1139000), 
    entry("Cardiff", 341000)
);

Collection Factory-Methoden in Java 9


Hervorragend, wenn Sie Java 9+ verwenden könnten. Auch diese Factory-Methode gibt eine unveränderliche Karte zurück.
Sourabh

6

Hier ist eine einfache Klasse, die das erreicht, was Sie wollen

import java.util.HashMap;

public class QuickHash extends HashMap<String,String> {
    public QuickHash(String...KeyValuePairs) {
        super(KeyValuePairs.length/2);
        for(int i=0;i<KeyValuePairs.length;i+=2)
            put(KeyValuePairs[i], KeyValuePairs[i+1]);
    }
}

Und dann, um es zu benutzen

Map<String, String> Foo=QuickHash(
    "a", "1",
    "b", "2"
);

Dies ergibt {a:1, b:2}


4
    boolean x;
    for (x = false, 
        map.put("One", new Integer(1)), 
        map.put("Two", new Integer(2)),      
        map.put("Three", new Integer(3)); x;);

Wenn man die Deklaration von ignoriert x(was notwendig ist, um eine Diagnose "nicht erreichbare Aussage" zu vermeiden), ist es technisch gesehen nur eine Aussage.


14
Das ist ekelhaft hacky.
Micah Stairs

1
@MicahStairs - Aber es ist nur eine Aussage.
Hot Licks

2
Stimmt, aber das ist die Art von Code, über die ich in der Produktion niemals stolpern möchte.
Micah Stairs

@ MicahStairs - Ich habe Schlimmeres gesehen.
Hot Licks

1
Omg ich habe heute danach gesucht, wie funktioniert dieser Code? Ich habe es in den Code zum Testen hinzugefügt, aber ich kann nicht herausfinden, wie es intern funktioniert ... :)
GOXR3PLUS

1

Sie können diese Dienstprogrammfunktion einer Dienstprogrammklasse hinzufügen:

public static <K, V> Map<K, V> mapOf(Object... keyValues) {
    Map<K, V> map = new HashMap<>();

    for (int index = 0; index < keyValues.length / 2; index++) {
        map.put((K)keyValues[index * 2], (V)keyValues[index * 2 + 1]);
    }

    return map;
}

Map<Integer, String> map1 = YourClass.mapOf(1, "value1", 2, "value2");
Map<String, String> map2 = YourClass.mapOf("key1", "value1", "key2", "value2");

Hinweis: In können Java 9Sie Map.of verwenden


-1

Ein anderer Ansatz könnte darin bestehen, eine spezielle Funktion zu schreiben, um alle Elementwerte aus einer Zeichenfolge durch einen regulären Ausdruck zu extrahieren:

import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Example {
    public static void main (String[] args){
        HashMap<String,Integer> hashMapStringInteger = createHashMapStringIntegerInOneStat("'one' => '1', 'two' => '2' , 'three'=>'3'  ");

        System.out.println(hashMapStringInteger); // {one=1, two=2, three=3}
    }

    private static HashMap<String, Integer> createHashMapStringIntegerInOneStat(String str) {
        HashMap<String, Integer> returnVar = new HashMap<String, Integer>();

        String currentStr = str;
        Pattern pattern1 = Pattern.compile("^\\s*'([^']*)'\\s*=\\s*>\\s*'([^']*)'\\s*,?\\s*(.*)$");

        // Parse all elements in the given string.
        boolean thereIsMore = true;
        while (thereIsMore){
            Matcher matcher = pattern1.matcher(currentStr);
            if (matcher.find()) {
                returnVar.put(matcher.group(1),Integer.valueOf(matcher.group(2)));
                currentStr = matcher.group(3);
            }
            else{
                thereIsMore = false;
            }
        }

        // Validate that all elements in the given string were parsed properly
        if (currentStr.length() > 0){
            System.out.println("WARNING: Problematic string format. given String: " + str);
        }

        return returnVar;
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.