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.

user387184
quelle

Antworten:

258

Du kannst das:

Map<String, Integer> hashMap = new HashMap<String, Integer>()
{{
     put("One", 1);
     put("Two", 2);
     put("Three", 3);
}};
Eng.Fouad
quelle
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?

JimmyT
quelle
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.

Timo Türschmann
quelle
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]
dfraser
quelle
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

Sadiq Ali
quelle
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}

Dakusan
quelle
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.

Hot Licks
quelle
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

R. Oosterholt
quelle
-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;
    }
}
Uri Ziv
quelle