Jeg vil legge til verdier til en HashMap
, som vil bli brukt ved metoder i samme klasse. Jeg har to løsninger:
- Legge til alle verdiene med
static
- Når den første metoden heter, legg til verdiene
Løsning nr. 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", "..-."); // ... }
Løsning 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", "..-."); // ... }
Hvilken er den mest effektive? Hvilken er den beste fremgangsmåten?
Kommentarer
- Hvorfor legger du det til et HashMap i utgangspunktet? Hvorfor ikke en matrise med 26 strenger?
- Hvordan løser en matrise med 26 strenger dette problemet? Spesielt hvordan gjør du kartleggingen? Du har den implisitte konverteringen fra A – > 0, B – > 0, …, i tankene?
- @Ali en siste serie håndterer uforanderlighet og initalisering. A- > 0, B- > 1 gjør det ganske pent å unngå mange av de andre utgavene av andre biblioteker som trengs, ekstra statiske blokker eller byggherrer. Det ' er klart og rimelig.
- @MichaelT Kanskje for dette spesielle eksemplet, gitt at brukeren vil ha kartlegging for morse-koden, en matrise av streng av størrelse 26 er greit, men det er ikke en generell løsning. Svaret mitt var mot en generell løsning, ikke denne. I mange tilfeller er domenet så stort, vi kan ikke bruke en direkte kartlegging til heltall, og vi må bruke en hashmap.
- @MichaelT btw, en matrise er bare størrelsesmessig uforanderlig, men du kan endre et av elementene. a [0] = " ny val ".
Svar
Løsningen din 1 kan være problematisk, da hashmap er statisk og vil kun initialiseres en gang, og deles av alle forekomster av klassen din. Er dette din tiltenkte oppførsel, eller ønsker du at hver forekomst har sitt eget kart? Hvis du bare ett kart, vil jeg foreslå å sende settet til konstruktøren i stedet for å bruke et statisk, for eksempel:
public class Data { private final Map<Character, String> codes; public Data(Map<Character, String> codes) { this.codes = codes} }
Din løsning 2 legger til overhead for lat initiering av settet, hver gang du trenger det, og legger til den stygge avkrysningen methodIsCalled
til logikken til programmet ditt. Jeg synes initiering av kartet i konstruktøren er et bedre alternativ.
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", "..-."); } }
Det andre spørsmålet du trenger å svare på er at hvis du endrer verdiene til dette hashmap senere eller ikke. Hvis du ikke endrer det, bør du se etter uforanderlige hashMaps. Ett alternativ er å bruke Collections.unmodifiableMap (map).
Du kan også bruke Google Guava-biblioteker som lar deg initialisere et kart i en linje og få et uforanderlig kart:
ImmutableMap.<Character, String>builder() .put("A", ".-") .put("B", "-...") .put("C", "-.-.") .put("D", "-..") .put("E", ".") .put("F", "..-.") .build();
Svar
Ingenting kan slå Guavas ImmutableMap med sitt optimerte minneforbruk, men her er et par rene løsninger:
/* 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", "..-."); // ... } }); }
Svar
Hvis du ikke insisterer på lat initialisering (og for et lite, ikke-voksende kart med 26 ting du ikke burde ikke t), hvorfor ikke optimalisere for lesbarhet i stedet? Jeg vil alltid bruke noe sånt som
private static Map<Character, String> codes = newMap( "A", ".-", "B", "-...", "C", "-.-.", ... );
(med en passende definert hjelperfunksjon newMap
).
Kommentarer
- Kan du til og med skrive newMap med parameterpakker?
- @ VF1 Du kan, hvis du definerer det som en generisk funksjon med varargs .
Svar
I disse tilfellene antar jeg at spørsmålet ikke handler om effektiv metode – men snarere når trenger faktisk at kartet er initialisert og klart ..
i tilfelle statisk initialisering – når klassen er lastet inn
, kan det være nødvendig med lat belastning hvis du trenger å sette «enormt «kart, og si ofte at disse verdiene kommer fra en dyr kilde (dvs. over hele nettverket), selv da trenger du kanskje ikke et eksternt flagg.
Collection.isEmpty () vil fortelle deg om det allerede er initialisert. eller ikke (forutsatt, selvfølgelig vil minst en verdi være der for å initialiseres)