Ik wil waarden toevoegen aan een HashMap, die zou worden gebruikt door methoden in de zelfde klas. Ik heb twee oplossingen:

  1. Alle waarden toevoegen met static
  2. Wanneer de eerste methode wordt aangeroepen, voeg je de waarden toe

Oplossing # 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", "..-."); // ... } 

Oplossing # 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", "..-."); // ... } 

Welke is het meest efficiënt? Welke is de beste praktijk?

Opmerkingen

  • Waarom zet je dat in de eerste plaats in een HashMap? Waarom niet een reeks van 26 strings?
  • Hoe lost een reeks van 26 strings dit probleem op? In het bijzonder, hoe doe je de mapping? Heeft u de impliciete conversie van A – > 0, B – > 0, … in gedachten?
  • @Ali een laatste array behandelt onveranderlijkheid en initialisering. A- > 0, B- > 1 vermijdt heel goed veel van de andere problemen van andere benodigde bibliotheken, extra statische blokken of Bouwers. Het ' is duidelijk en redelijk.
  • @MichaelT Misschien voor dit specifieke voorbeeld, aangezien de gebruiker mapping wil hebben voor de morsecode, een array van String van maat 26 is prima, maar het is geen algemene oplossing. Mijn antwoord was in de richting van een algemene oplossing, niet deze specifieke. In veel gevallen is het domein zo groot dat we geen directe toewijzing aan gehele getallen kunnen gebruiken en we hebben een hashmap nodig.
  • @MichaelT trouwens, een array is alleen qua grootte onveranderlijk, maar je kunt wijzigen een van de elementen. a [0] = " nieuwe waarde ".

Antwoord

Uw oplossing 1 kan problematisch zijn, aangezien de hashmap statisch is en slechts één keer wordt geïnitialiseerd, en wordt gedeeld door alle instanties van uw klas. Is dit uw beoogde gedrag of wilt u dat elke instantie een eigen kaart heeft? Als je maar één map hebt, zou ik willen voorstellen om de set door te geven aan de constructor in plaats van een statische te gebruiken, bijvoorbeeld:

public class Data { private final Map<Character, String> codes; public Data(Map<Character, String> codes) { this.codes = codes} } 

Jouw oplossing 2 voegt toe de overhead van luie initialisatie van de set, elke keer dat je het nodig hebt, en voegt de lelijke controle methodIsCalled toe aan de logica van je programma. Ik denk dat het initialiseren van de kaart in de constructor een betere optie is.

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", "..-."); } } 

De andere vraag die je moet beantwoorden is dat als je de waarden van deze hashmap later wijzigt of niet. Als u het niet wijzigt, kunt u beter zoeken naar onveranderlijke hashMaps. Een optie is om Collections.unmodifiableMap (map) te gebruiken.

U kunt ook Google Guava-bibliotheken gebruiken om een kaart te initialiseren in één regel en krijg een onveranderlijke kaart:

ImmutableMap.<Character, String>builder() .put("A", ".-") .put("B", "-...") .put("C", "-.-.") .put("D", "-..") .put("E", ".") .put("F", "..-.") .build(); 

Antwoord

Niets kan verslaan Guavas ImmutableMap met zijn geoptimaliseerd geheugengebruik, maar hier zijn een paar pure oplossingen:

/* 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", "..-."); // ... } }); } 

Antwoord

Als je niet aandringt op luie initialisatie (en voor een kleine, niet-groeiende kaart van 26 items zou je dat niet moeten doen), waarom zou je dan niet optimaliseren voor leesbaarheid? Ik zou altijd zoiets als

private static Map<Character, String> codes = newMap( "A", ".-", "B", "-...", "C", "-.-.", ... ); 

gebruiken (met een passend gedefinieerde hulpfunctie newMap).

Reacties

  • Kun je zelfs newMap schrijven met parameterpakketten?
  • @ VF1 Dat kan, als je het definieert als een generieke functie met varargs .

Antwoord

In deze gevallen gaat de vraag naar mijn mening niet over een efficiënte methode – maar wanneer gaat u heb die map eigenlijk geïnitialiseerd en klaar nodig.

in het geval van statische initialisatie – tegen de tijd dat de klasse is geladen

kan je benadering van lazy loading nodig zijn als je huge “map, en zeg vaak dat die waarden afkomstig zijn van een dure bron (dwz via het netwerk), zelfs dan heb je misschien geen externe vlag nodig.

Collection.isEmpty () zou je vertellen of dat al geïnitialiseerd is of niet (op voorwaarde dat er natuurlijk minstens één waarde is om te worden geïnitialiseerd)

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *