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

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

Soluzione n. 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?

Commenti

  • Perché la metti in una HashMap in primo luogo? Perché non un array di 26 stringhe?
  • In che modo un array di 26 stringhe risolve questo problema? In particolare, come si fa la mappatura? Hai la conversione implicita da A – > 0, B – > 0, …, in mente?
  • @Ali un array finale gestisce limmutabilità e linitalizzazione. A- > 0, B- > 1 evita abbastanza bene molti degli altri problemi di altre librerie necessarie, blocchi statici extra o costruttori. ' è chiaro e ragionevole.
  • @MichaelT Forse per questo particolare esempio, dato che lutente desidera avere una mappatura per il codice morse, un array di String della taglia 26 va bene, tuttavia, non è una soluzione generale. La mia risposta era verso una soluzione generale, non questa in particolare. In molti casi, il dominio è così grande, non possiamo usare una mappatura diretta a numeri interi e dobbiamo usare una hashmap.
  • @MichaelT btw, un array è immutabile solo in termini di dimensioni, ma puoi cambiare uno dei suoi elementi. a [0] = " nuovo val ".

Risposta

La tua soluzione 1 potrebbe essere problematica, poiché lhashmap è statica e verrà inizializzata solo una volta ed è condivisa da tutte le istanze della tua classe. È questo il tuo comportamento previsto o desideri che ogni istanza abbia la propria mappa? Se hai una sola mappa, ti 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 dellinizializzazione pigra del set, ogni volta che ne hai bisogno, e aggiunge il brutto segno di spunta methodIsCalled alla logica del tuo programma. Penso che inizializzare la mappa nel costruttore sia unopzione 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", "..-."); } } 

Laltra domanda a cui devi rispondere è che se cambi i valori di questa hashmap in seguito o no. Se non la modifichi, è meglio cercare hashMaps immutabili. Unopzione è usare Collections.unmodifiableMap (map).

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

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

Answer

Niente può battere ImmutableMap di Guava con il suo consumo di memoria ottimizzato, ma qui ci sono un paio 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", "..-."); // ... } }); } 

Answer

Se non insisti su uninizializzazione lenta (e per una piccola mappa non in crescita di 26 elementi non dovresti “t), 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 di supporto adeguatamente definita newMap).

Commenti

  • Puoi anche scrivere newMap con i pacchetti di parametri?
  • @ VF1 Puoi, se la definisci come una funzione generica con varargs .

Risposta

In questi casi, suppongo che la domanda non riguardi un metodo efficiente, ma piuttosto quando ha effettivamente bisogno che la mappa sia inizializzata e pronta ..

nel caso di inizializzazione statica – prima che la classe venga caricata

il tuo approccio di caricamento lento potrebbe essere necessario se devi impostare “enorme “map, e diciamo spesso che quei valori provengono da una fonte costosa (cioè attraverso la rete), anche in questo caso potresti non aver bisogno di un flag esterno.

Collection.isEmpty () ti dirà se è già stato inizializzato oppure no (ammesso che almeno un valore debba essere inizializzato)

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *