Hoi! In deze les gaan we dieper in op Java HashMap . Eerder hebben we gegevensstructuren bestudeerd waarin de elementen als zichzelf zijn opgeslagen. In een array of een ArrayList / LinkedList slaan we een aantal elementen op. Maar wat als onze taak een beetje verandert?
HashMap: wat voor kaart is dit?  - 1
Stel je de volgende taak voor: maak een lijst van 100 mensen die de naam en het paspoortnummer van elke persoon opslaat. In principe is dit niet zo moeilijk. U kunt bijvoorbeeld beide in een string stoppen en vervolgens een lijst met deze strings maken: "Amelia Aguilar, 4211 717171". Maar deze oplossing heeft twee nadelen. Ten eerste hebben we mogelijk de mogelijkheid nodig om op paspoortnummer te zoeken. En dit zal problematisch zijn gezien dit formaat voor informatieopslag. Ten tweede houdt niets ons tegen om twee verschillende personen met hetzelfde paspoortnummer aan te maken. En dit is de grootste tekortkoming van onze oplossing. Dit mag nooit: geen twee mensen hebben hetzelfde paspoortnummer. Een nieuwe datastructuur komt ons te hulp: Map. Het is ook bekend als een "associatieve array", maar deze term wordt niet vaak gebruikt. Vaker wordt het een "woordenboek" of "kaart" genoemd. :) Hoe verschilt het fundamenteel van de gegevensstructuren die we eerder hebben overwogen? Vooral in het feit dat gegevens in een kaart worden opgeslagen als sleutel-waardeparen. Alles kan dienen als sleutels en waarden: getallen, strings of objecten van andere klassen. Vandaag bestuderen we de meest gebruikelijke implementatie van de klasse Map : Java HashMap . HashMap: wat voor kaart is dit?  - 2

Dus, wat moeten we weten over HashMap in Java?

Het is heel eenvoudig om te maken:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();
}
Hier maken we een woordenboek waarin elementen worden opgeslagen als "getal-tekenreeks"-paren. Het nummer fungeert als de sleutel en de tekenreeks als de waarde. We specificeren ook het sleuteltype (Integer) en het waardetype (String). Waarom? Ten eerste is een HashMap- sleutel altijd uniek. Dit past perfect bij ons, aangezien we het paspoortnummer als sleutel kunnen gebruiken en duplicaten kunnen voorkomen. De waarde is een tekenreeks met de volledige naam (verschillende mensen kunnen dezelfde naam hebben; daar hoeven wij ons geen zorgen over te maken). Het toevoegen van een nieuw paar aan de HashMap ziet er als volgt uit:

public class Main {

   public static void main(String[] args) {
       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put (212133, "Bridget Logan");
       passportsAndNames.put (162348, "Ivan the Great");
       passportsAndNames.put(8082771, "Donald John Trump");
       System.out.println(passportsAndNames);
   }
}
Hiervoor gebruiken we de methode put() . Bovendien overschrijft HashMap de methode toString() zodat deze op de console kan worden weergegeven. De uitvoer ziet er als volgt uit: {212133=Bridget Logan, 8082771=Donald John Trump, 162348=Ivan de Grote} Laten we nu eens kijken of de sleutels echt uniek zijn? Laten we proberen een nieuw element toe te voegen met een sleutel die al in de kaart is gebruikt :

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");
   passportsAndNames.put(162348, "Albert Kent");// This key has already been used
   System.out.println(passportsAndNames);
}
Uitvoer: {212133=Bridget Logan, 8082771=Donald John Trump, 162348=Albert Kent} Zoals u kunt zien, is de vorige waarde gekoppeld aan sleutel 162348 overschreven. We gebruiken de term "sleutel" niet voor niets. Waarden in een HashMap zijn toegankelijk met behulp van de sleutel, maar niet andersom. De sleutel kan niet worden verkregen met behulp van een waarde, aangezien de waarden mogelijk niet uniek zijn. Dit is duidelijk te zien bij het ophalen of verwijderen van een element uit de HashMap :

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   String lidiaName = passportsAndNames.get(212133);
   System.out.println(lidiaName);

   passportsAndNames.remove(162348);
   System.out.println(passportsAndNames);
}
Om een ​​waarde te krijgen of een paar uit het woordenboek te verwijderen, moeten we de unieke sleutel doorgeven aan de get() en remove() die overeenkomt met de waarde. In tegenstelling tot arrays en lijsten heeft een HashMap in Java geen numerieke indexen: waarden worden benaderd met behulp van de sleutel. Console-uitvoer: Bridget Logan {212133=Bridget Logan, 8082771=Donald John Trump} Met de klassen ArrayList en LinkedList kunnen we controleren of de lijst een bepaald element bevat. Met Java HashMap kunnen we dit doen. Bovendien kunnen we dit voor beide leden van het paar doen: Dit is wat de containKey() (controleert op een sleutel) en de comesValue()(controleert op een waarde) methoden zijn voor.

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.containsKey(11111));
   System.out.println(passportsAndNames.containsValue("Donald John Trump"));
}
Uitvoer: false true Een ander handig kenmerk van HashMap in Java is het feit dat u afzonderlijke lijsten kunt krijgen met alle sleutels en alle waarden. Dit wordt bereikt met de methoden keySet() en waarden() :

public class Main {

   public static void main(String[] args) {
       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put (212133, "Bridget Logan");
       passportsAndNames.put (162348, "Ivan the Great");
       passportsAndNames.put(8082771, "Donald John Trump");

       Set keys = passportsAndNames.keySet();
       System.out.println("Keys: " + keys);

       ArrayList<String> values = new ArrayList<>(passportsAndNames.values());
       System.out.println("Values: " + values);
   }
}
De sleutels worden geëxtraheerd in een Set , die we nog niet hebben behandeld. Het is bijzonder omdat het geen herhalende elementen kan bevatten. Het belangrijkste is nu om te onthouden dat de lijst met alle sleutels uit een HashMap kan worden opgehaald in een afzonderlijke verzameling. In het voorbeeld hebben we de waarden opgeslagen in een gewone ArrayList . Console-uitvoer: Toetsen: [212133, 8082771, 162348] Waarden: [Bridget Logan, Donald John Trump, Ivan de Grote] De methoden size() en clear() doen precies hetzelfde als in de vorige structuren die we hebben besproken: de eerste geeft het aantal elementen terug dat momenteel in het woordenboek staat, de tweede verwijdert alle elementen.

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.size());
   passportsAndNames.clear();
   System.out.println(passportsAndNames);
}
Uitvoer: 3 {} Om te controleren of er ten minste één element in onze HashMap zit , kunnen we de methode isEmpty() gebruiken:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   if (!passportsAndNames.isEmpty()) {

       System.out.println(passportsAndNames);
   }
}
Uitvoer: {212133=Bridget Logan, 8082771=Donald John Trump, 162348=Ivan de Grote} Nu zullen we alleen uitvoeren naar de console na een voorafgaande controle. :) Een ander interessant punt is dat twee kaarten kunnen worden gecombineerd tot één. Dit gebeurde met behulp van de methode putAll() . We noemen het op de eerste HashMap , geven de tweede door als argument en de elementen van de tweede worden toegevoegd aan de eerste:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();
   HashMap<Integer, String> passportsAndNames2 = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   passportsAndNames2.put(917352, "Clifford Patrick");
   passportsAndNames2.put(925648, "Mitchell Salgado");

   passportsAndNames.putAll(passportsAndNames2);
   System.out.println(passportsAndNames);
}
Uitvoer: {917352=Clifford Patrick, 212133=Bridget Logan, 8082771=Donald John Trump, 925648=Mitchell Salgado, 162348=Ivan de Grote} Alle paren in paspoortenAndNames2 zijn gekopieerd naar paspoortenAndNames . Overweeg nu een ingewikkelder voorbeeld. In het bijzonder itereren over een HashMap in een lus.

for (Map.Entry<Integer, String> entry: passportsAndNames.entrySet()) {
   System.out.println(entry);
}
De klasse Map.Entry geeft het sleutel-waardepaar in het woordenboek aan. De methode entrySet() retourneert een lijst van alle paren in onze HashMap . Omdat onze kaart uit deze Map.Entry- paren bestaat, itereren we over paren, niet over afzonderlijke sleutels of waarden. Uitvoer: 212133=Bridget Logan 8082771=Donald John Trump 162348=Ivan de Grote Vergeet ook niet de officiële Oracle- documentatie voor HashMap te bestuderen .