HashMap – Java dátové štruktúry
Java HashMap je jednou z množstva dátových štruktúr pre efektívnu prácu s údajmi. V našom seriáli si postupne predstavíme aj rôzne ďalšie kolekcie. Ukážeme si, ako s nimi pracovať, aké operácie sa s nimi dajú robiť či aké sú najčastejšie používané metódy. Spomenieme tiež ich výhody a nevýhody a kedy je vhodné konkrétnu dátovú štruktúru použiť.

V článku sa dozvieš:
V tomto článku sa zameriame na jednu z dátových štruktúr – triedu HashMap, ktorá umožňuje ukladanie dvojíc kľúč-hodnota a poskytuje rýchly prístup k hodnotám na základe kľúčov.

HashMap v Jave – predstavenie dátovej štruktúry
Java HashMap trieda je implementáciou rozhrania Map v balíku java.util. Umožňuje ukladanie dvojíc kľúč-hodnota, kde každý kľúč je unikátny a mapuje sa na konkrétnu hodnotu. Táto implementácia poskytuje všetky voliteľné operácie s mapou a povoľuje hodnoty null a kľúč null.
Trieda HashMap je približne ekvivalentná triede Hashtable, okrem toho, že je HashMap nesynchronizovaná a povoľuje nulové hodnoty. HashMap využíva hashovaciu tabuľku na ukladanie prvkov, čo zabezpečuje rýchle vyhľadávanie, vkladanie a odstraňovanie prvkov s priemernou časovou zložitosťou O(1). Je dôležité podotknúť, že HashMap neudržuje poradie vložených prvkov.
HashMap – konštruktory
Na vytvorenie inštancie HashMap máme k dispozícií niekoľko konštruktorov:
1. Prázdna HashMap s predvolenou kapacitou a faktorom zaťaženia
Vytvorí prázdnu HashMap s predvolenou počiatočnou kapacitou (16) a faktorom zaťaženia (0.75).
HashMap<K, V> map = new HashMap<>();
2. HashMap s určenou počiatočnou kapacitou
Vytvorí prázdnu HashMap s určenou počiatočnou kapacitou a predvoleným faktorom zaťaženia (0.75).
HashMap<K, V> map = new HashMap<>(int initialCapacity);
3. HashMap s určenou počiatočnou kapacitou a faktorom zaťaženia
Vytvorí prázdnu HashMap s určenou počiatočnou kapacitou a faktorom zaťaženia.
HashMap<K, V> map = new HashMap<>(int initialCapacity, float loadFactor);
4. HashMap skonštruovaný z Map
Vytvorí novú hašovaciu tabuľku s rovnakým mapovaním ako daná Map.
HashMap(Map<? extends K,? extends V> m)
Initial capacity, Load Factor (faktor zaťaženia), Hash Function
Týmto technickým pojmom spojených s vytvorením hashovacej mapy sme sa už venovali pri triede HashTable, preto ich tu nebudem opakovať.
HashMap – základné operácie
Medzi základné operácie, ktoré môžeme vykonávať s HashMap, patria:
- Vkladanie dvojíc
Pridanie dvojice kľúč-hodnota pomocou metódy put(K key, V value). Ak sa vloží nová dvojica so zhodným kľúčom, stará hodnota sa prepíše novou. - Prístup k hodnotám
Získanie hodnoty na základe kľúča pomocou metódy get(Object key). - Odstraňovanie dvojíc
Odstránenie dvojice kľúč-hodnota pomocou metódy remove(Object key). - Test prázdnosti
Metóda isEmpty() nám zistí, či HashMap vôbec obsahuje nejakú dvojicu. - Kontrola existencie kľúča alebo hodnoty
Overenie prítomnosti hodnoty sa robí pomocou metódy containsValue(Object value).
Overenie prítomnosti kľúča sa robí pomocou metódy containsKey(Object key). - Zistenie veľkosti
Metóda size() vráti počet dvojíc v tabuľke. - Vyprázdnenie tabuľky
Metóda clear() odstráni všetky dvojice z tabuľky. - Iterácia cez dvojice
Pomocou metód keySet(), values() alebo entrySet() môžeme iterovať cez kľúče, hodnoty alebo celé páry.
Dokumentácia k Java HashMap
Kompletný prehľad metód triedy HashMap, nájdeš v oficiálnej dokumentácii.
HashMap – výhody a nevýhody
Nevýhody HashMap
- Rýchlosť operácií
Operácie ako vloženie (put()), vyhľadanie (get()) a odstránenie (remove()) majú priemerne konštantnú časovú zložitosť O(1) vďaka hashovaciemu mechanizmu. - Flexibilita v používaní kľúčov a hodnôt
Môžno používať akékoľvek objekty ako kľúč a hodnotu, pokiaľ kľúč implementuje metódy hashCode() a equals(). - Jednoduchosť použitia
API je prehľadné a intuitívne, čo uľahčuje prácu s mapovacími dátovými štruktúrami.
Nevýhody HashMap
- Nezachováva poradie prvkov
HashMap negarantuje poradie vloženia, čo môže byť problém, ak je dôležité udržať následnosť dát.
Ak potrebuješ poradie, použi LinkedHashMap.
- Nie je synchronizovaná
HashMap nie je thread-safe, čo znamená, že v viacvláknovom prostredí môže dôjsť ku konfliktom.
Ak potrebuješ synchronizovanú verziu, použi Collections.synchronizedMap(new HashMap<>()) alebo ConcurrentHashMap.
- Citlivosť na implementáciu hashCode a equals
Ak trieda, ktorú ukladáme ako prvok, nemá správne implementované metódy hashCode() a equals(), môže to viesť k neočakávanému správaniu a zníženiu výkonu. - Výkon v prípade kolízií
Pri veľkom počte kolízií (keď viaceré prvky majú rovnaký hash kód) môže dôjsť k zníženiu výkonu, pretože operácie sa môžu správať pomalšie.
HashMap – kedy ju použiť a kedy nie
Java HashMap je vhodná v nasledovných prípadoch:
- Keď potrebuješ rýchly prístup k dátam na základe kľúča.
- Ak nie je potrebné zachovávať poradie vložených prvkov.
Naopak, nie je vhodná, ak potrebujeme zachovať poradie vložených prvkov. V takom prípade je lepšou voľbou LinkedHashMap.
Príklad použitia HashMap v Jave
HashMap vyniká efektívnym ukladaním dvojíc kľúč-hodnota a ich rýchlym vyhľadaním vďaka hashovacej metóde, keď ich potrebujeme načítať a použiť. Preto majú hashovacie mapy všestranné použitie.
Použitie kolekcie HashMap si ilustrujeme na príklade volieb. Zadefinujeme si zoznam kandidátov a pomocou metódy voting() budeme simulovať tajné hlasovanie. Dátovú štruktúru HashMap použijeme na spočítavanie hlasov, kde kľúč bude meno kandidáta a hodnota aktuálny počet hlasov. Nakoniec vypíšeme počet hlasov pre jednotlivých kandidátov.
VotingSystem.java
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Arrays;
import java.util.Random;
public class VotingSystem {
public static void main(String[] args) {
// List of candidates
List<String> candidates = Arrays.asList("Alica", "Beata", "Cyril", "Dominik", "Jozef");
// Create a HashMap to store vote counts
HashMap<String, Integer> voteCounts = new HashMap<>();
// Run the voting simulation with N votes
int numberOfVotes = 1000; // Change this number for different simulation sizes
voting(voteCounts, candidates, numberOfVotes);
// Display final election results
System.out.println("Election results:");
for (Map.Entry<String, Integer> entry : voteCounts.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue() + " votes");
}
}
// Voting method that simulates N random votes
public static void voting(HashMap<String, Integer> voteCounts, List<String> candidates, int N) {
Random random = new Random();
for (int i = 0; i < N; i++) {
// Randomly select a candidate from the list
String selectedCandidate = candidates.get(random.nextInt(candidates.size()));
// Add vote to the candidate in HashMap
voteCounts.put(selectedCandidate, voteCounts.getOrDefault(selectedCandidate, 0) + 1);
}
}
}
Výstup z tohto príkladu je:
Pripravili sme pre teba súbory so spomínaným príkladom vo forme kódu, ktorý si môžeš spustiť priamo v Jave. Stiahni si Java kód pre HashMap tu.