Ich möchte einem HashMap Werte hinzufügen, die von Methoden in der verwendet werden selbe Klasse. Ich habe zwei Lösungen:

  1. Hinzufügen aller Werte mit static
  2. Wenn die erste Methode aufgerufen wird, fügen Sie die Werte

Lösung 1:

private static Map<Character, String> codes = new HashMap<>(); static { codes.put("A", ".-"); codes.put("B", "-..."); codes.put("C", "-.-."); codes.put("D", "-.."); codes.put("E", "."); codes.put("F", "..-."); // ... } 

Lösung 2:

boolean methodIsCalled = false; public static char decode(String s) { if(!methodIsCalled) { addValues(); methodIsCalled = true; } // ... } private static void addValues() { codes.put("A", ".-"); codes.put("B", "-..."); codes.put("C", "-.-."); codes.put("D", "-.."); codes.put("E", "."); codes.put("F", "..-."); // ... } 

Welches ist das effizienteste? Welches ist die beste Vorgehensweise?

Kommentare

  • Warum fügen Sie das überhaupt in eine HashMap ein? Warum nicht ein Array mit 26 Strings?
  • Wie löst ein Array mit 26 Strings dieses Problem? Wie wird das Mapping durchgeführt? Sie haben die implizite Konvertierung von A – > 0, B – > 0, … im Auge?
  • @Ali ein endgültiges Array behandelt Unveränderlichkeit und Initialisierung. A- > 0, B- > 1 vermeidet ganz gut viele andere Probleme anderer Bibliotheken, zusätzliche statische Blöcke oder Bauherren. ' ist klar und vernünftig.
  • @MichaelT Vielleicht für dieses spezielle Beispiel, da der Benutzer eine Zuordnung für den Morsecode haben möchte, ein Array von Zeichenfolgen von Größe 26 ist in Ordnung, es ist jedoch keine allgemeine Lösung. Meine Antwort war auf eine allgemeine Lösung gerichtet, nicht auf diese. In vielen Fällen ist die Domäne so groß, dass wir keine direkte Zuordnung zu Ganzzahlen verwenden können und eine Hashmap verwenden müssen.
  • @MichaelT Übrigens ist ein Array nur in Bezug auf die Größe unveränderlich, aber Sie können es ändern eines seiner Elemente. a [0] = " neuer Wert ".

Antwort

Ihre Lösung 1 ist möglicherweise problematisch, da die Hashmap statisch ist und nur einmal initialisiert wird und von allen Instanzen Ihrer Klasse gemeinsam genutzt wird. Ist dies Ihr beabsichtigtes Verhalten oder möchten Sie, dass jede Instanz eine eigene Zuordnung hat? Wenn Sie nur eine Karte haben, würde ich vorschlagen, die Menge an den Konstruktor zu übergeben, anstatt eine statische zu verwenden, zum Beispiel:

public class Data { private final Map<Character, String> codes; public Data(Map<Character, String> codes) { this.codes = codes} } 

Ihre Lösung 2 fügt hinzu Der Aufwand für die verzögerte Initilisierung des Sets bei jedem Bedarf und das Hinzufügen der hässlichen Prüfung methodIsCalled zur Logik Ihres Programms. Ich denke, das Initilieren der Map im Konstruktor ist eine bessere Option.

public class Data { private final Map<Character, String> codes; public Data() { this.codes = new HashMap<>(); codes.put("A", ".-"); codes.put("B", "-..."); codes.put("C", "-.-."); codes.put("D", "-.."); codes.put("E", "."); codes.put("F", "..-."); } } 

Die andere Frage, die Sie beantworten müssen, lautet: Wenn Sie die Werte dieser Hashmap später ändern oder nicht. Wenn Sie es nicht ändern, suchen Sie besser nach unveränderlichen HashMaps. Eine Option ist die Verwendung von Collections.unmodifizierbarer Karte (Karte).

Sie können auch Google Guava-Bibliotheken verwenden, um eine Karte in zu initialisieren eine Zeile und erhalten Sie eine unveränderliche Karte:

ImmutableMap.<Character, String>builder() .put("A", ".-") .put("B", "-...") .put("C", "-.-.") .put("D", "-..") .put("E", ".") .put("F", "..-.") .build(); 

Antwort

Nichts kann schlagen Guavas ImmutableMap mit seinem optimierten Speicherverbrauch, aber hier sind zwei reine Lösungen:

/* Name of the class has to be "Main" only if the class is public. */ class Ideone { private static final Map<Character, String> codes1; static { Map<Character, String> temp= new HashMap<Character, String>(); temp.put("A", ".-"); temp.put("B", "-..."); temp.put("C", "-.-."); temp.put("D", "-.."); temp.put("E", "."); temp.put("F", "..-."); // ... codes1 = Collections.unmodifiableMap(temp); } private static final Map<Character, String> codes2 = Collections.unmodifiableMap(new HashMap<Character, String>() { { put("A", ".-"); put("B", "-..."); put("C", "-.-."); put("D", "-.."); put("E", "."); put("F", "..-."); // ... } }); } 

Antwort

Wenn Sie nicht auf einer verzögerten Initialisierung bestehen (und für eine kleine, nicht wachsende Karte mit 26 Elementen sollten Sie dies nicht tun), warum nicht stattdessen die Lesbarkeit optimieren? Ich würde immer so etwas wie

private static Map<Character, String> codes = newMap( "A", ".-", "B", "-...", "C", "-.-.", ... ); 

verwenden (mit einer entsprechend definierten Hilfsfunktion newMap).

Kommentare

  • Können Sie sogar newMap mit Parameterpaketen schreiben?
  • @ VF1 Sie können dies, wenn Sie es als generische Funktion mit varargs definieren .

Antwort

In diesen Fällen geht es vermutlich nicht um eine effiziente Methode, sondern wann Sie Diese Karte muss tatsächlich initialisiert und bereit sein.

Bei statischer Initialisierung – bis die Zeitklasse geladen ist

ist Ihr Ansatz zum verzögerten Laden möglicherweise erforderlich, wenn Sie „riesig“ einstellen müssen „map, und sagen Sie oft, dass diese Werte von einer teuren Quelle stammen (dh über das Netzwerk), auch dann benötigen Sie möglicherweise kein externes Flag.

Collection.isEmpty () würde Ihnen mitteilen, ob dies bereits initialisiert wurde oder nicht (vorausgesetzt natürlich, dass mindestens ein Wert zum Initialisieren vorhanden ist)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.