2012-11-18 6 views
10

Ich muss eine statische Map erstellen, die eine gegebene String auf ein Array von int s abbildet.So erstellen Sie eine statische Zuordnung von String -> Array

Mit anderen Worten, würde Ich mag, wie etwas definieren:

"fred" -> {1,2,5,8} 
"dave" -> {5,6,8,10,11} 
"bart" -> {7,22,10010} 
... etc 

Gibt es eine einfache Möglichkeit, dies in Java zu tun?

Und wenn möglich, würde ich gerne static Konstanten sowohl für die String als auch die int Werte verwenden.

EDIT: Um zu klären, was ich von static Konstanten für die Werte gemeint, und zu geben, was ich sehe, der richtige Code zu sein, hier ist mein erster Stich an der Lösung:

public final static String FRED_TEXT = "fred"; 
public final static String DAVE_TEXT = "dave"; 

public final static int ONE = 1; 
public final static int TWO = 2; 
public final static int THREE = 3; 
public final static int FOUR = 4; 

public final static HashMap<String, int[]> myMap = new HashMap<String, int[]>(); 
static { 
    myMap.put(FRED_TEXT, new int[] {ONE, TWO, FOUR}); 
    myMap.put(DAVE_TEXT, new int[] {TWO, THREE}); 
} 

Hinweis, Diese Namen sind nicht das, was ich tatsächlich benutzen würde. Dies ist nur ein künstliches Beispiel.

Antwort

21

Sie nicht müssen Deklaration und Initialisierung getrennt werden. Wenn Sie wissen, wie es geht, kann alles in einer Linie gemacht werden!

// assumes your code declaring the constants ONE, FRED_TEXT etc is before this line 
private static final Map<String, int[]> myMap = Collections.unmodifiableMap(
    new HashMap<String, int[]>() {{ 
     put(FRED_TEXT, new int[] {ONE, TWO, FOUR}); 
     put(DAVE_TEXT, new int[] {TWO, THREE}); 
    }}); 

Was wir hier haben, ist eine anonyme Klasse mit einem inialization block - ein Block von Code, der auf dem Bau nach Konstruktor ausgeführt, die wir hier verwendet haben, um die Karte zu laden (dies wird manchmal fälschlicherweise als „Doppelstrebe Initialisierung "- Ich nehme an, es gibt zwei benachbarte Klammern = aber es gibt eigentlich keine solche Sache.

Die zwei coolen Dinge über dies ist a) es heiratet die Deklaration mit dem Inhalt und b) weil die Initialisierung in-line ist, können Sie auch einen Inline-Anruf an Collections.unmodifiableMap(), was zu einer sauberen Ein-Linie Deklaration, Initialisierung und Konvertierung in unmodifizierbar.

Wenn Sie nicht wollen/müssen die Karte nicht änderbar zu sein, lassen Sie diesen Anruf:

private static final Map<String, int[]> myMap = new HashMap<String, int[]>() {{ 
    put(FRED_TEXT, new int[] {ONE, TWO, FOUR}); 
    put(DAVE_TEXT, new int[] {TWO, THREE}); 
}}; 
+0

Ahh, aber ich muss die Karte in einer Super-Klasse deklarieren, aber füllen Sie es in einer Unterklasse. Tut mir leid, ich weiß, das war nicht in meiner ursprünglichen Frage. Ich würde immer noch den "statischen" Block in diesem Fall benötigen? – DuncanKinnear

+0

Aber da dies "statisch" ist, wie kann es "ein Block von Code sein, der auf Konstruktion nach Konstruktor ausgeführt wird"? Ich dachte, dass Konstruktion nicht auftritt, wenn Sie auf "statischen" Code verweisen. – DuncanKinnear

+1

@Duncankinnear die Instanz ist statisch, aber der Block ist nicht. Der Block ist ein Instanzenblock der anonymen Klasse, die statisch instanziiert wird. Die anonyme Klasse ist eine Unterklasse von 'HashMap', von der immer nur eine Instanz existiert (' new' wird nur einmal aufgerufen) – Bohemian

1
static Map<String, int[]> map = new HashMap<>(); 

Die Karte ist statisch, können Sie es ohne eine Instanz der Klasse zugreifen kann es in definiert ist. Ich weiß nicht, was Sie meinen die Schlüssel mit, die Werte und auch statisch, weil es keinen Sinn macht mir.

+0

Siehe meine Bearbeitung für ein Beispiel der Verwendung der statischen Konstanten. – DuncanKinnear

5

Sie müssen Ihre statische Karte separat deklarieren und initialisieren. Hier

ist die Erklärung Stück:

private static final Map<String,int[]> MyMap; 

Hier ist die Initialisierung Stück:

static { 
    Map<String,int[]> tmpMap = new HashMap<String,int[]>(); 
    tmpMap.put("fred", new int[] {1,2,5,8}); 
    tmpMap.put("dave", new int[] {5,6,8,10,11}); 
    tmpMap.put("bart", new int[] {7,22,10010}); 
    MyMap = Collections.unmodifiableMap(tmpMap); 
} 

Leider Arrays sind immer beschreibbar in Java. Sie könnten MyMap nicht zuordnen, aber Sie könnten Werte aus anderen Teilen Ihres Programms, die auf die Karte zugreifen, hinzufügen oder entfernen.

+1

+1 für den statischen Initialisierungsblock – jlordo

+1

Natürlich sind die Karte und die Arrays in diesem Beispiel schreibbar. – cdhowie

+0

@cdhowie Sie haben Recht, ich habe der Antwort einen Absatz hinzugefügt, um diesen Punkt zu unterstreichen. – dasblinkenlight

0
public class ExampleClass { 
    public final static HashMap consts = new HashMap(); 
    static 
    { 
     constants.put("A", "The Letter A"); 
     constants.put("B", "The Letter B"); 
     constants.put("C", "The Letter C"); 
    } 
    /* Rest of your class that needs to know the consts */ 
} 
+0

Korrigieren Sie mich, wenn ich falsch bin, aber statische Blockierung wird vor der Initialisierung der "costs" ausgeführt? –

+0

Ich habe getestet und was auch immer Sie geschrieben haben, ist korrekt. Aber wenn wir den Intialisierungsblock von costs und den statischen Block wechseln, wird ein Kompilierungsfehler ausgelöst. Ich hätte nie gedacht, dass die Reihenfolge der Definition der Elemente in Java irgendwelche Auswirkungen hätte. –

5

Aus Gründen der Vollständigkeit, da dies das erste Ergebnis in Google für ‚Java ist statisch Karte definieren 'In Java 8 können Sie dies nun tun.

Collections.unmodifiableMap(Stream.of(
      new SimpleEntry<>("a", new int[]{1,2,3}), 
      new SimpleEntry<>("b", new int[]{1,2,3}), 
      new SimpleEntry<>("c", new int[]{1,2,3})) 
      .collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue()))); 

Dieser schöne Teil dabei ist, dass wir keine anonymen Klassen mehr mit der doppelten Klammer Syntax ({{ }})

wir dies mit einigem Code können dann erweitern schaffen das Muster wie dieser Kerl aufzuzuräumen hat hier http://minborgsjavapot.blogspot.ca/2014/12/java-8-initializing-maps-in-smartest-way.html

public static <K, V> Map.Entry<K, V> entry(K key, V value) { 
    return new AbstractMap.SimpleEntry<>(key, value); 
} 

public static <K, U> Collector<Map.Entry<K, U>, ?, Map<K, U>> entriesToMap() { 
    return Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue()); 
} 

public static <K, U> Collector<Map.Entry<K, U>, ?, ConcurrentMap<K, U>> entriesToConcurrentMap() { 
    return Collectors.toConcurrentMap((e) -> e.getKey(), (e) -> e.getValue()); 
} 

Endergebnisses

Collections.unmodifiableMap(Stream.of(
      entry("a", new int[]{1,2,3}), 
      entry("b", new int[]{1,2,3}), 
      entry("c", new int[]{1,2,3})) 
      .collect(entriesToMap())); 

, die uns eine Concurrent Unmodifiable Map geben würde.

+0

Danke für die Antwort. Schade, dass wir auf Java 6 feststecken. – DuncanKinnear

Verwandte Themen