Jeg vil føje værdier til en HashMap
, som ville blive brugt ved metoder i samme klasse. Jeg har to løsninger:
- Tilføjelse af alle værdier med
static
- Når den første metode kaldes, skal du tilføje værdierne
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 nr. 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 bedste praksis?
Kommentarer
- Hvorfor sætter du det i første omgang i en HashMap? Hvorfor ikke en matrix på 26 strenge?
- Hvordan løser en matrix på 26 strenge dette problem? Især hvordan man laver kortlægningen? Du har den implicitte konvertering fra A – > 0, B – > 0, …, i tankerne?
- @Ali en sidste række håndterer uforanderlighed og initalisering. A- > 0, B- > 1 gør det ganske pænt og undgår mange af de andre udgaver af andre nødvendige biblioteker, ekstra statiske blokke eller bygherrer. Det ' er klart og rimeligt.
- @MichaelT Måske til dette særlige eksempel, i betragtning af at brugeren ønsker at have kortlægning til morse-koden, en række streng i størrelse 26 er fint, men det er ikke en generel løsning. Mit svar var på en generel løsning, ikke denne særlige. I mange tilfælde er domænet så stort, at vi ikke kan bruge en direkte kortlægning til heltal, og vi skal bruge et hashmap.
- @MichaelT btw, et array er kun størrelsesmæssigt uforanderligt, men du kan ændre et af dets elementer. a [0] = " ny val ".
Svar
Din løsning 1 kan være problematisk, da hashmap er statisk og kun initialiseres en gang og deles af alle forekomster af din klasse. Er dette din tiltænkte opførsel, eller ønsker du, at hver instans har sit eget kort? Hvis du kun har et kort, vil jeg foreslå at videresende sættet til konstruktøren i stedet for at bruge en 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 tilføjer omkostningerne ved doven initiering af sættet, hver gang du har brug for det, og tilføjer den grimme afkrydsningsfelt methodIsCalled
til logikken i dit program. Jeg synes, at initiering af kortet i konstruktøren er en bedre mulighed.
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 andet spørgsmål, du skal svare på, er, at hvis du ændrer værdierne for denne hashmap senere eller ikke. Hvis du ikke ændrer det, skal du bedre kigge efter uforanderlige hashMaps. En mulighed er at bruge Collections.unmodifiableMap (kort).
Du kan også bruge Google Guava-biblioteker, så du kan initialisere et kort i en linje og få et uforanderligt kort:
ImmutableMap.<Character, String>builder() .put("A", ".-") .put("B", "-...") .put("C", "-.-.") .put("D", "-..") .put("E", ".") .put("F", "..-.") .build();
Svar
Intet kan slå Guavas ImmutableMap med sit optimerede hukommelsesforbrug, 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å doven initialisering (og for et lille, ikke-voksende kort med 26 emner, bør du ikke t), hvorfor så ikke optimere til læsbarhed i stedet? Jeg vil altid bruge noget som
private static Map<Character, String> codes = newMap( "A", ".-", "B", "-...", "C", "-.-.", ... );
(med en passende defineret hjælperfunktion newMap
).
Kommentarer
- Kan du endda skrive newMap med parameterpakker?
- @ VF1 Du kan, hvis du definerer det som en generisk funktion med varargs .
Svar
I disse tilfælde antager jeg, at spørgsmålet ikke handler om effektiv metode – men snarere hvornår skal du har faktisk brug for det kort initialiseret og klar ..
i tilfælde af statisk initialisering – efter klassen er indlæst
kan din dovne indlæsningsmetode være nødvendig, hvis du har brug for at indstille “enorm “kort, og sig ofte, at disse værdier kommer fra en dyr kilde (dvs. på tværs af netværket), selv da behøver du muligvis ikke et eksternt flag.
Collection.isEmpty () fortæller dig, om det allerede er initialiseret. eller ikke (forudsat, naturligvis ville mindst en værdi være der for at blive initialiseret)