Chci přidat hodnoty do HashMap
, které by byly použity metodami v stejná třída. Mám dvě řešení:
- Přidání všech hodnot pomocí
static
- Když se volá první metoda, přidejte hodnoty
Řešení č. 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", "..-."); // ... }
Řešení č. 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", "..-."); // ... }
Který z nich je nejúčinnější? Který je nejlepší postup?
Komentáře
- Proč to vlastně vkládáte do HashMap? Proč ne řada 26 řetězců?
- Jak tento problém vyřeší řada 26 řetězců? Zejména, jak provést mapování? Máte na mysli implicitní převod z A – > 0, B – > 0, …?
- @Ali konečné pole zpracovává neměnnost a initalizaci. A- > 0, B- > 1 to dělá celkem pěkně a vyhýbá se mnoha dalším problémům s potřebnými knihovnami, navíc statické bloky nebo stavitelé. Je to ' jasné a rozumné.
- @MichaelT Možná pro tento konkrétní příklad, vzhledem k tomu, že uživatel chce mít mapování morseovského kódu, řadu řetězců velikosti 26 je v pořádku, nejde však o obecné řešení. Moje odpověď směřovala k obecnému řešení, nikoli k tomuto konkrétnímu. V mnoha případech je doména tak velká, že nemůžeme použít přímé mapování na celá čísla a musíme použít hashmapu.
- @MichaelT btw, pole je pouze neměnné z hlediska velikosti, ale můžete ho změnit jeden z jeho prvků. a [0] = " nová val ".
odpověď
Vaše řešení 1 může být problematické, protože hashmap je statický a bude inicializován pouze jednou a je sdílen všemi instancemi vaší třídy. Je to vaše zamýšlené chování nebo chcete, aby každá instance měla svou vlastní mapu? Pokud máte pouze jednu mapu, doporučil bych předat sadu konstruktoru namísto použití statické, například:
public class Data { private final Map<Character, String> codes; public Data(Map<Character, String> codes) { this.codes = codes} }
Vaše řešení 2 přidává režii líné inicializace sady, pokaždé, když ji potřebujete, a přidá do logiky vašeho programu ošklivý šek methodIsCalled
. Myslím, že inicializace mapy v konstruktoru je lepší volba.
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", "..-."); } }
Další otázka, na kterou si musíte odpovědět, je, že pokud později změníte hodnoty tohoto hashmapu nebo ne. Pokud to nezměníte, měli byste hledat neměnné hashMaps. Jednou z možností je použít Collections.unmodifiableMap (mapa).
Můžete také použít knihovny Google Guava, které vám umožní inicializovat mapu v jeden řádek a získejte neměnnou mapu:
ImmutableMap.<Character, String>builder() .put("A", ".-") .put("B", "-...") .put("C", "-.-.") .put("D", "-..") .put("E", ".") .put("F", "..-.") .build();
Odpověď
Nic nemůže porazit Guava „s ImmutableMap s optimalizovanou spotřebou paměti, ale zde je pár čistých řešení:
/* 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", "..-."); // ... } }); }
odpověď
Pokud netrváte na líné inicializaci (a pro malou nerostoucí mapu 26 položek byste neměli), proč ne optimalizovat místo toho čitelnost? Vždy bych použil něco jako
private static Map<Character, String> codes = newMap( "A", ".-", "B", "-...", "C", "-.-.", ... );
(s vhodně definovanou pomocnou funkcí newMap
).
Komentáře
- Můžete dokonce psát newMap s balíčky parametrů?
- @ VF1 Můžete, pokud ji definujete jako obecnou funkci s varargs .
Odpověď
Předpokládám, že v těchto případech nejde o efektivní metodu – ale spíše kdy ve skutečnosti potřebujete tuto mapu inicializovanou a připravenou ..
v případě statické inicializace – v době, kdy je třída načtena
může být nutný váš líný způsob načítání, pokud potřebujete nastavit „obrovský „mapa, a řekněme často, že tyto hodnoty pocházejí z nákladného zdroje (tj. napříč sítí), i tak možná nebudete potřebovat externí příznak.
Collection.isEmpty () vám řekne, zda již byla inicializována nebo ne (za předpokladu, že by tam byla alespoň jedna hodnota, která by měla být inicializována)