Una mappa memorizza coppie chiave-valore
Una HashMap (di java.util) memorizza associazioni: ogni chiave corrisponde a un valore, e cerchi i valori tramite la loro chiave in un tempo circa costante. Pensa a un dizionario: la parola è la chiave, la definizione è il valore.
I due parametri di tipo sono <KeyType, ValueType>. Qui le chiavi sono String e i valori sono Integer. Come per ArrayList, di solito dichiari la variabile con l'interfaccia Map e costruisci una HashMap.
put, get e sovrascrittura
Due cose da tenere a mente:
- Una chiave è unica.
putcon una chiave esistente ne sostituisce il valore e restituisce quello vecchio. getsu una chiave mancante restituiscenull, non un errore. L'unboxing automatico di quelnullin unintlancia unaNullPointerException, una fonte comune di bug.
getOrDefault evita la trappola del null
Invece di controllare ogni volta se c'è null, chiedi un valore di riserva:
È il modo più pulito per gestire ricerche di valori "forse presenti", e porta direttamente allo schema più famoso della HashMap.
Contare le occorrenze
Contare quante volte compare ogni elemento è il compito da manuale di una HashMap:
Lo schema map.put(key, map.getOrDefault(key, 0) + 1) si legge come "prendi il conteggio attuale (o zero), aggiungi uno, rimettilo a posto". Un equivalente più ordinato è counts.merge(word, 1, Integer::sum).
Verificare e rimuovere
putIfAbsent(key, value) scrive solo quando la chiave manca: utile per l'inizializzazione pigra.
Scorrere una HashMap
Il ciclo più comune percorre entrySet(), dandoti insieme ogni chiave e valore:
Se ti servono solo le chiavi o solo i valori:
Puoi anche usare forEach con una lambda: ages.forEach((name, age) -> System.out.println(name + ": " + age));.
HashMap non mantiene l'ordine
Una HashMap non garantisce alcun ordine di iterazione: è quello prodotto dall'hashing e può cambiare da un'esecuzione all'altra. Se ti serve un ordine prevedibile:
LinkedHashMapmantiene l'ordine di inserimento.TreeMaptiene le chiavi ordinate secondo l'ordine naturale (o secondo unComparatorche fornisci tu).
Tutte e tre implementano l'interfaccia Map, quindi cambiare è una modifica di una riga al costruttore.
Le chiavi devono essere hashabili
HashMap trova le coppie calcolando l'hash della chiave, quindi hashCode() ed equals() di una chiave devono essere coerenti. I tipi predefiniti come String e Integer lo fanno già correttamente. Se usi una tua classe come chiave, fai l'override sia di equals sia di hashCode, altrimenti due oggetti "uguali" nel significato finiranno in bucket diversi e le tue ricerche falliranno in modo misterioso.
Prossimo passo: HashSet
Una HashMap risponde alla domanda "quale valore è memorizzato sotto questa chiave?". Quando ti interessa solo sapere se qualcosa è presente, cioè un insieme di valori unici senza dati associati, lo strumento giusto è HashSet, il prossimo argomento.
Domande frequenti
Come si crea una HashMap in Java?
Dichiarala con due parametri di tipo, il tipo della chiave e il tipo del valore, e chiama il costruttore: Map<String, Integer> ages = new HashMap<>();. Poi aggiungi coppie con ages.put("Ada", 36); e leggile con ages.get("Ada");. Importa java.util.HashMap e java.util.Map.
Come si scorre una HashMap in Java?
Scorri map.entrySet() con un ciclo for-each per ottenere insieme ogni chiave e valore: for (Map.Entry<String, Integer> e : map.entrySet()) { ... }, leggendo e.getKey() ed e.getValue(). Puoi anche scorrere map.keySet() per le sole chiavi o map.values() per i soli valori. Nota che una HashMap non mantiene l'ordine di inserimento.
Qual è la differenza tra get e getOrDefault?
get(key) restituisce il valore di una chiave, oppure null se la chiave non c'è, e questo può portare a una NullPointerException se usi direttamente il risultato. getOrDefault(key, fallback) restituisce il valore se presente, altrimenti il valore di riserva che passi, così eviti il controllo su null. È particolarmente comodo per contare: counts.put(c, counts.getOrDefault(c, 0) + 1).