Ricordiamo che una mappa è un dato strutturato costituito da un insieme di coppie chiave-valore e ciascuna chiave può essere utilizzata solo una volta in una singola mappa. Questo argomento copre 9 domande di base sull'utilizzo di Map in Java e sulle classi implementate. Per semplicità, userò le generalizzazioni negli esempi . Pertanto scriverò semplicemente Map, senza specificare lo specificatore Map. Ma puoi supporre che entrambi i valori di K e V siano comparabili, il che significa che K estende Comparable e V estende anche Comparable .
0. Conversione di una mappa in un elenco
In Java, l' interfaccia Mappa offre tre tipi di raccolte: un set di chiavi, un set di valori e un set di valori-chiave. Tutti possono essere trasformati in un List utilizzando il costruttore o il metodoaddAll()
. Il frammento di codice seguente illustra come creare un ArrayList da una mappa.
// list of keys
List keyList = new ArrayList(Map.keySet());
//list of values
List valueList = new ArrayList(Map.valueSet());
//list key-value
List entryList = new ArrayList(Map.entrySet());
1. Passa in rassegna tutti i valori nella mappa
Percorrere ciascuna coppia chiave-valore è la procedura più elementare per percorrere una mappa. In Java, ogni coppia viene memorizzata in un campo Map chiamato Map.Entry .Map.entrySet()
restituisce un insieme di valori-chiave, quindi il modo più efficiente per scorrere tutti i valori di una mappa sarebbe:
for(Entry entry: Map.entrySet()) {
//get the key
K key = entry.getKey();
//get value
V value = entry.getValue();
}
Possiamo anche usare Iterator
, soprattutto nelle versioni precedenti a JDK 1.5
Iterator itr = Map.entrySet().iterator();
while(itr.hasNext()) {
Entry entry = itr.next();
//get the key
K key = entry.getKey();
//get value
V value = entry.getValue();
}
2. Ordinazione della mappa tramite chiavi
Organizzare le mappe per tasti è un'altra procedura comunemente utilizzata. Il primo modo è aggiungere Map.Entry all'elenco e ordinare utilizzando un comparatore che ordina in base ai valori.List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {
@Override
public int compare(Entry e1, Entry e2) {
return e1.getKey().compareTo(e2.getKey());
}
});
Un altro modo: utilizzare SortedMap , che, inoltre, dispone anche le sue chiavi in ordine. Tuttavia, tutte le chiavi devono incorporare Comparable o essere accettate dal comparatore. Una delle classi implementate SortedMap
è TreeMap . Il suo costruttore accetta un comparatore. Il codice seguente mostra come trasformarne uno normale Map
in uno ordinato.
SortedMap sortedMap = new TreeMap(new Comparator() {
@Override
public int compare(K k1, K k2) {
return k1.compareTo(k2);
}
});
sortedMap.putAll(Map);
3. Mappa dell'ordine in base ai valori
In questo caso l'aggiunta di una mappa all'elenco e il relativo ordinamento funzionano, ma questa volta è necessario utilizzareEntry.getValue()
. Il codice seguente è quasi lo stesso di prima.
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {
@Override
public int compare(Entry e1, Entry e2) {
return e1.getValue().compareTo(e2.getValue());
}
});
Possiamo ancora usarlo SortedMap
in questo caso, ma solo se i valori sono univoci. In questo caso, puoi trasformare la coppia chiave-valore in una chiave-valore. Questa soluzione presenta gravi limitazioni e non è consigliata da me.
4. Inizializzazione di una mappa statica/immutabile
Quando vuoi che una mappa rimanga immutabile, un buon modo è copiarla su una mappa immutabile. Questa tecnica di programmazione difensiva ti aiuterà a creare una mappa che non solo sia sicura da usare, ma anche thread-safe. Per inizializzare una mappa statica/immutabile, possiamo utilizzare un inizializzatorestatic
(vedi sotto). Il problema con questo codice è che nonostante dichiariamo una Map come static final
, possiamo ancora lavorarci dopo l'inizializzazione, ad esempio Test.Map.put(3,"three");
. Quindi non è vera immutabilità. Per creare una mappa immutabile utilizzando un inizializzatore statico, abbiamo bisogno di una classe super anonima, che aggiungeremo alla mappa immutabile nell'ultimo passaggio di inizializzazione. Si prega di guardare la seconda parte del codice. Quando verrà generata un'eccezione UnsupportedOperationException se si esegue Test.Map.put(3,"three");
.
public class Test {
private static final Map Map;
static {
Map = new HashMap();
Map.put(1, "one");
Map.put(2, "two");
}
}
public class Test {
private static final Map Map;
static {
Map aMap = new HashMap();
aMap.put(1, "one");
aMap.put(2, "two");
Map = Collections.unmodifiableMap(aMap);
}
}
La libreria Guava supporta anche vari modi per inizializzare raccolte statiche e immutabili. Per ulteriori informazioni sui vantaggi dell'utilità delle raccolte immutabili di Guava, vedere la sezione Raccolte immutabili nel Guava How-to .
5. Differenza tra HashMap, TreeMap e Hashtable
Esistono tre implementazioni principali dell'interfaccia Map in Java: HashMap , TreeMap e Hashtable . Le differenze principali sono le seguenti:- Ordine di passaggio . HashMap e HashTable non garantiscono l'ordinamento della Mappa; in particolare non garantiscono che l'ordine rimanga identico nel tempo. Ma
TreeMap
ordinerà tutti i valori nell'ordine naturale delle chiavi o tramite un comparatore. - Coppie chiave-valore valide.
HashMap
ti consente di avere una chiave nulla e un valore nullo.HashTable
non consente una chiave nulla o un valore nullo. SeTreeMap
viene utilizzato l'ordine naturale o il comparatore non consente una chiave nulla, verrà generata un'eccezione. - Sincronizzazione . Solo
HashTable
sincronizzato, il resto no. Tuttavia, "se non è necessaria un'implementazione thread-safe, si consiglia di utilizzare "HashMap
inveceHashTable
.
. | HashMap | HashTable | TreeMap
-------------------------------------------------------
Упорядочивание |нет |нет | да
null в ключ-meaning | да-да | нет-нет | нет-да
синхронизировано | нет | да | нет
производительность | O(1) | O(1) | O(log n)
воплощение | корзины | корзины | красно-чёрное дерево
Maggiori informazioni sulla relazione HashMap vs. Mappa ad albero vs. Tabella hash vs. LinkedHashMap .
6. Mappa con ricerca/visualizzazione inversa
A volte abbiamo bisogno di una serie di coppie chiave-chiave, il che significa che i valori sono unici quanto le chiavi (uno schema uno a uno). Questa coerenza consente di creare una "vista/ricerca invertita" sulla Mappa. Cioè, possiamo trovare una chiave in base al suo valore. Questa struttura dati è chiamata mappa bidirezionale , che sfortunatamente non è supportata dal JDK. Sia Apache Common Collections che Guava offrono implementazioni di mappe bidirezionali chiamate rispettivamente BidiMap e BiMap. Entrambi introducono un vincolo che impone una mappatura 1:1 tra chiavi e valori.7. Copia superficiale della mappa
Quasi tutte, se non tutte, le mappe in Java contengono un costruttore di copia per un'altra mappa. Ma la procedura di copia non è sincronizzata. Ciò significa che quando un thread copia una mappa, un altro thread può modificarne la struttura. Per evitare un'improvvisa desincronizzazione della copia, in questo caso è necessario utilizzarne unoCollections.synchronizedMap()
.
Map copiedMap = Collections.synchronizedMap(Map);
Un altro modo interessante per copiare superficialmente è utilizzare l'estensione clone()
. Ma NON è consigliato nemmeno dal creatore del framework delle raccolte Java, Joshua Bloch. Nel dibattito " Copy Constructor vs. Cloning ", prende posizione: Citazione: "Spesso fornisco un metodo di clonazione pubblica in classi concrete perché le persone si aspettano che siano lì. ... è un peccato che la clonazione non funzioni, ma è successo... La clonazione è un punto debole e penso che le persone dovrebbero essere avvertite dei suoi limiti." Per questo motivo non ti mostro nemmeno come utilizzare il metodo clone()
per copiare Map
8. Crea una mappa vuota
SeMap
immutabile, utilizzare:
Map = Collections.emptyMap();
Oppure utilizzare qualsiasi altra forma di realizzazione. Per esempio:
Map = new HashMap();
FINE
GO TO FULL VERSION