Értékeket szeretnék hozzáadni egy HashMap
fájlhoz, amelyet a metódusok a ugyanabba az osztályba. Két megoldásom van:
- Az összes érték hozzáadása
static
- Amikor az első metódust meghívjuk, adjuk hozzá az
1. megoldás:
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", "..-."); // ... }
2. megoldás:
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", "..-."); // ... }
Melyik a leghatékonyabb? Melyik a legjobb gyakorlat?
Megjegyzések
- Miért teszi ezt egy HashMap-ba? Miért nem 26 karakterlánc tömb?
- Hogyan oldja meg a 26 karakterlánc tömb ezt a problémát? Különösen, hogyan kell elvégezni a feltérképezést? Az A – > 0, B – > 0, … eredetű implicit konverzióra gondolsz?
- @Ali egy végső tömb kezeli a változtathatatlanságot és az initalizációt. A- > 0, B- > 1 nagyon szépen elkerüli a szükséges egyéb könyvtárak számos egyéb kérdését, extra statikus blokkokat vagy építők. ' világos és ésszerű.
- @MichaelT Talán ennél a konkrét példánál, tekintettel arra, hogy a felhasználó szeretné leképezni a morzekódot, egy tömb String a 26-os méretben rendben van, azonban ez nem általános megoldás. Válaszom egy általános megoldás felé irányult, nem pedig ez a konkrét. Sok esetben a domain akkora, hogy nem használhatunk közvetlen leképezést egész számokra, és hashmap-ot kell használnunk.
- @MichaelT btw, egy tömb csak méretenként változtathatatlan, de változtathat egyik eleme. a [0] = " új val ".
Válasz
Az 1. megoldásod problémás lehet, mivel a hashmap statikus, és csak egyszer inicializálódik, és az osztályod összes példánya megosztja. Ez a szándékolt viselkedésed, vagy azt akarod, hogy minden példánynak legyen saját térképe? Ha csak egy térkép van, akkor azt javaslom, hogy statikus helyett adja át a halmazt a konstruktornak, például:
public class Data { private final Map<Character, String> codes; public Data(Map<Character, String> codes) { this.codes = codes} }
A 2. megoldásod hozzáadódik a halmaz lusta kezdeményezésének költsége, valahányszor szükség van rá, és hozzáadja a program logikájához a csúnya ellenőrzést methodIsCalled
. Szerintem a térkép inicializálása a konstruktorban jobb megoldás.
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", "..-."); } }
A másik kérdés, amire válaszolnia kell, az az, hogy ha később módosítja a hashmap értékeit vagy nem. Ha nem változtatja meg, akkor jobb, ha megváltoztathatatlan hashMaps-okat keres. Az egyik lehetőség a Collections.unmodifiableMap (térkép) használata.
Használhatja a Google Guava könyvtárakat is, amelyek lehetővé teszik a térkép inicializálását a egy sort és megváltoztathatatlan térképet kap:
ImmutableMap.<Character, String>builder() .put("A", ".-") .put("B", "-...") .put("C", "-.-.") .put("D", "-..") .put("E", ".") .put("F", "..-.") .build();
Válasz
Semmi nem verhető Guava ImmutableMap optimalizált memóriafelhasználásával, de itt van egy pár tiszta megoldás:
/* 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", "..-."); // ... } }); }
Válasz
Ha nem ragaszkodik a lusta inicializáláshoz (és egy 26 elemből álló kicsi, nem növekvő térképhez nem kellene), akkor miért ne optimalizálna az olvashatóság érdekében? Mindig valami olyasmit használnék, hogy
private static Map<Character, String> codes = newMap( "A", ".-", "B", "-...", "C", "-.-.", ... );
(megfelelően definiált segítőfunkcióval newMap
).
Megjegyzések
- Írhat-e még newMap-ot is paramétercsomagokkal?
- @ VF1 Megteheti, ha általános függvényként definiálja a varargokkal .
Válasz
Ezekben az esetekben feltételezem, hogy a kérdés nem a hatékony módszerről szól, hanem inkább arról, hogy mikor valóban szüksége van arra a térképre, amely inicializálva van, és készen áll.
statikus inicializálás esetén – az osztály betöltődésekor
a lusta betöltési módszerre szükség lehet, ha a „hatalmas” beállítást kell megadnia “térkép, és gyakran azt mondják, hogy ezek az értékek drága forrásból származnak (azaz a hálózaton keresztül), akkor is lehet, hogy nincs szükség külső zászlóra.
A Collection.isEmpty () megmondja, hogy ezt már inicializálták-e vagy sem (feltéve, hogy természetesen legalább egy értéket inicializálni lehetne)