Vreau să adaug valori la un HashMap
, care ar fi folosit de metodele din aceeasi clasa. Am două soluții:
- Adăugarea tuturor valorilor cu
static
- Când se apelează prima metodă, adăugați valorile
Soluția # 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", "..-."); // ... }
Soluția # 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", "..-."); // ... }
Care este cel mai eficient? Care este cea mai bună practică?
Comentarii
- De ce puneți asta într-un HashMap în primul rând? De ce nu o matrice de 26 de șiruri?
- Cum rezolvă această problemă o matrice de 26 de șiruri? În special, cum să faceți cartografierea? Aveți în vedere conversia implicită de la A – > 0, B – > 0, …?
- @Ali o matrice finală gestionează imuabilitatea și inițializarea. A- > 0, B- > 1 o face destul de frumos evitând multe dintre celelalte probleme ale altor biblioteci necesare, blocuri statice suplimentare sau constructori. Este ' clar și rezonabil.
- @MichaelT Poate pentru acest exemplu, dat fiind faptul că utilizatorul dorește să aibă mapare pentru codul morse, o matrice de șiruri de dimensiunea 26 este bine, totuși, nu este o soluție generală. Răspunsul meu a fost către o soluție generală, nu aceasta specială. În multe cazuri, domeniul este atât de mare, încât nu putem folosi o mapare directă la numere întregi și trebuie să folosim un hashmap.
- @MichaelT btw, o matrice este doar imutabilă în funcție de dimensiune, dar puteți schimba unul dintre elementele sale. a [0] = " new val ".
Răspuns
Soluția dvs. 1 poate fi problematică, deoarece hashmap-ul este static și va fi inițializat o singură dată și este partajat de toate instanțele clasei dvs. Acesta este comportamentul dvs. intenționat sau doriți ca fiecare instanță să aibă propria hartă? Dacă aveți o singură hartă, aș sugera să treceți setul către constructor în loc să îl folosiți pe unul static, de exemplu:
public class Data { private final Map<Character, String> codes; public Data(Map<Character, String> codes) { this.codes = codes} }
Soluția dvs. 2 adaugă cheltuielile de inițializare leneșă a setului, de fiecare dată când aveți nevoie de acesta, și adaugă verificarea urâtă methodIsCalled
la logica programului dvs. Cred că inițializarea hărții în constructor este o opțiune mai bună.
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", "..-."); } }
Cealaltă întrebare la care trebuie să răspundeți este că, dacă modificați valorile acestui hashmap mai târziu sau nu. Dacă nu îl schimbați, ar trebui să căutați hashMaps imuabile. O opțiune este să utilizați Collections.unmodifiableMap (hartă).
Puteți utiliza și bibliotecile Google Guava pentru a vă permite să inițializați o hartă în o singură linie și obțineți o hartă imuabilă:
ImmutableMap.<Character, String>builder() .put("A", ".-") .put("B", "-...") .put("C", "-.-.") .put("D", "-..") .put("E", ".") .put("F", "..-.") .build();
Răspuns
Nimic nu poate bate Guava ImmutableMap cu consumul de memorie optimizat, dar iată o pereche de soluții 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", "..-."); // ... } }); }
Răspuns
Dacă nu insistați pe inițializarea leneșă (și pentru o hartă mică, care nu crește, cu 26 de elemente, nu ar trebui să „t), atunci de ce să nu optimizați pentru lizibilitate? Aș folosi întotdeauna ceva de genul
private static Map<Character, String> codes = newMap( "A", ".-", "B", "-...", "C", "-.-.", ... );
(cu o funcție de ajutor adecvată definită newMap
).
Comentarii
- Puteți scrie chiar newMap cu pachete de parametri?
- @ VF1 Puteți, dacă îl definiți ca o funcție generică cu varargs .
Răspuns
În aceste cazuri, presupun că întrebarea nu se referă la o metodă eficientă – ci mai degrabă când de fapt, aveți nevoie de acea hartă inițializată și gata ..
în cazul inițializării statice – până când se încarcă clasa de timp
abordarea dvs. de încărcare leneșă poate fi necesară dacă trebuie să setați „uriaș „harta și spuneți adesea că aceste valori provin dintr-o sursă costisitoare (adică în întreaga rețea), chiar și atunci este posibil să nu aveți nevoie de un semnal extern.
Collection.isEmpty () vă va spune dacă a fost deja inițializat sau nu (cu condiția, desigur, cel puțin o valoare ar fi acolo pentru a fi inițializată)