Aggiunta di valori a HashMap

1

Voglio aggiungere valori a HashMap , che verrebbe utilizzato da metodi della stessa classe. Ho due soluzioni:

  1. Aggiunta di tutti i valori con static
  2. Quando viene chiamato il primo metodo, aggiungi i valori

Soluzione 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', "..-.");
    // ...
}

Soluzione n. 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', "..-.");
    // ...
}

Qual è il più efficiente? Qual è la migliore pratica?

    
posta TheCoffeeCup 01.01.2015 - 04:48
fonte

4 risposte

3

La tua soluzione 1 potrebbe essere problematica, poiché l'hashmap è statica e verrà inizializzata solo una volta, ed è condivisa da tutte le istanze della tua classe. È questo il tuo comportamento previsto o vuoi che ogni istanza abbia la sua mappa? Se si è una sola mappa, suggerirei di passare il set al costruttore invece di usarne uno statico, ad esempio:

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

La tua soluzione 2 aggiunge il sovraccarico di inizializzazione pigra del set, ogni volta che ne hai bisogno, e aggiunge il brutto controllo methodIsCalled alla logica del tuo programma. Penso che l'avvio della mappa nel costruttore sia un'opzione migliore.

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', "..-.");
  } 
}

L'altra domanda a cui devi rispondere è che se cambi i valori di questa hashmap più tardi o meno. Se non lo cambi, è meglio cercare hashMaps immutabili. Un'opzione è da usare Collections.unmodifiableMap (mappa).

Puoi anche utilizzare le librerie Google Guava per consentire di inizializzare una mappa in una riga e ottenere una mappa immutabile:

ImmutableMap.<Character, String>builder()
     .put('A', ".-")
     .put('B', "-...")
     .put('C', "-.-.")
     .put('D', "-..")
     .put('E', ".")
     .put('F', "..-.")
     .build();
    
risposta data 01.01.2015 - 05:12
fonte
3

Niente può battere ImmutableMap di Guava con il suo consumo di memoria ottimizzato, ma ecco una coppia di soluzioni pure:

/* 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', "..-.");
      // ...
    }
  });
}
    
risposta data 01.01.2015 - 10:32
fonte
0

Se non insisti sull'inizializzazione pigra (e per una piccola mappa non crescente di 26 elementi che non dovresti), allora perché non ottimizzare invece la leggibilità? Vorrei sempre usare qualcosa come

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

(con una funzione helper adeguatamente definita newMap ).

    
risposta data 01.01.2015 - 09:45
fonte
0

In questi casi, suppongo che la domanda non riguardi il metodo efficiente - ma piuttosto quando hai effettivamente bisogno di quella mappa inizializzata e pronta ...

nel caso di inizializzazione statica - in base alla classe di tempo caricata

il tuo approccio di caricamento lento può essere necessario se devi impostare una mappa "enorme" e dire che spesso questi valori provengono da una fonte costosa (vale a dire attraverso la rete), anche se potresti non aver bisogno di un flag esterno.

Collection.isEmpty () ti direbbe se è già stato inizializzato o no (a condizione, ovviamente, almeno un valore sarebbe lì da inizializzare)

    
risposta data 01.01.2015 - 15:34
fonte

Leggi altre domande sui tag