Recuerde que un mapa son datos estructurados que constan de un conjunto de pares clave-valor, y cada clave solo se puede usar una vez en un único mapa. Este tema cubre 9 preguntas básicas sobre el uso de Map en Java y sus clases implementadas. Para simplificar, usaré generalizaciones en los ejemplos . Por lo tanto, escribiré simplemente Mapa, sin especificar el especificador de Mapa. Pero se puede suponer que ambos valores de K y V son comparables, lo que significa que K extiende Comparable y V también extiende Comparable .
0. Convertir un mapa en una lista
En Java, la interfaz Map ofrece tres tipos de colecciones: un conjunto de claves, un conjunto de valores y un conjunto de valores-clave. Todos ellos se pueden convertir en una Lista usando el constructor o métodoaddAll()
. El siguiente fragmento de código demuestra cómo crear una ArrayList a partir de un mapa.
// lista de llaves
List keyList = new ArrayList(Map.keySet());
//lista de valores
List valueList = new ArrayList(Map.valueSet());
//lista clave-valor
List entryList = new ArrayList(Map.entrySet());
1. Recorra todos los valores en el mapa.
Recorrer cada par clave-valor es el procedimiento más básico para recorrer un mapa. En Java, cada par se almacena en un campo de mapa llamado Map.Entry .Map.entrySet()
devuelve un conjunto de valores-clave, por lo que la forma más eficiente de iterar sobre todos los valores de un Mapa sería:
for(Entry entry: Map.entrySet()) {
//Consigue la llave
K key = entry.getKey();
// obtener valor
V value = entry.getValue();
}
También podemos usar Iterator
, especialmente en versiones anteriores a JDK 1.5
Iterator itr = Map.entrySet().iterator();
while(itr.hasNext()) {
Entry entry = itr.next();
//Consigue la llave
K key = entry.getKey();
// obtener valor
V value = entry.getValue();
}
2. Ordenar mapa por claves
Organizar mapas por claves es otro procedimiento comúnmente utilizado. La primera forma es agregar Map.Entry a la lista y ordenar usando un comparador que ordena por valores.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());
}
});
Otra forma: utilizar SortedMap , que, además, también ordena sus claves. Sin embargo, todas las claves deben incluir Comparable o ser aceptadas por el comparador. Una de las clases implementadas SortedMap
es TreeMap . Su constructor acepta un comparador. El siguiente código muestra cómo convertir uno normal Map
en uno ordenado.
SortedMap sortedMap = new TreeMap(new Comparator() {
@Override
public int compare(K k1, K k2) {
return k1.compareTo(k2);
}
});
sortedMap.putAll(Map);
3. Ordenar mapa por valores
Agregar un mapa a la lista y luego ordenarlo funciona en este caso, pero esta vez debes usarEntry.getValue()
. El siguiente código es casi el mismo que antes.
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());
}
});
Todavía podemos usarlo SortedMap
en este caso, pero solo si los valores son únicos. En este caso, puede convertir el par clave-valor en un par clave-valor. Esta solución tiene graves limitaciones y no la recomiendo.
4. Inicializando un mapa estático/inmutable
Cuando desee que un mapa permanezca inmutable, una buena forma es copiarlo en un mapa inmutable. Esta técnica de programación defensiva le ayudará a crear un mapa que no sólo sea seguro de usar, sino también seguro para subprocesos. Para inicializar un mapa estático/inmutable, podemos usar un inicializadorstatic
(ver más abajo). El problema con este código es que a pesar de declarar un mapa como static final
, todavía podemos trabajar con él después de la inicialización, por ejemplo Test.Map.put(3,"three");
. Entonces no es una inmutabilidad real. Para crear un mapa inmutable usando un inicializador estático, necesitamos una clase súper anónima, que agregaremos al mapa inmutable en el último paso de inicialización. Mire la segunda parte del código. Cuándo se generará una excepción UnsupportedOperationException si ejecuta 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 biblioteca Guava también admite varias formas de inicializar colecciones estáticas e inmutables. Para obtener más información sobre los beneficios de la utilidad de colecciones inmutables de Guava, consulte la sección Colecciones inmutables en Guava How-to .
5. Diferencia entre HashMap, TreeMap y Hashtable
Hay tres implementaciones principales de la interfaz Map en Java: HashMap , TreeMap y Hashtable . Las principales diferencias son las siguientes:- Orden de paso . HashMap y HashTable no garantizan el orden del Mapa; en particular, no garantizan que el pedido se mantendrá igual en el tiempo. Pero
TreeMap
ordenará todos los valores en el "orden natural" de las claves o mediante un comparador. - Pares clave-valor válidos.
HashMap
le permite tener una clave nula y un valor nulo.HashTable
no permite una clave nula o un valor nulo. SiTreeMap
se utiliza el orden natural o el comparador no permite una clave nula, se generará una excepción. - Sincronización . Solo
HashTable
sincronizados, el resto no. Pero "si no se necesita una implementación segura para subprocesos, se recomienda utilizar "HashMap
en su lugarHashTable
.
. | HashMap | HashTable | TreeMap
-------------------------------------------------------
Упорядочивание |нет |нет | да
null в ключ-significado | да-да | нет-нет | нет-да
синхронизировано | нет | да | нет
производительность | O(1) | O(1) | O(log n)
воплощение | корзины | корзины | красно-чёрное дерево
Lea más sobre la relación HashMap vs. Mapa de árbol vs. Tabla hash vs. LinkedHashMap .
6. Mapa con búsqueda/vista inversa
A veces, necesitamos un conjunto de pares clave-clave, lo que significa que los valores son tan únicos como las claves (un patrón uno a uno). Esta coherencia le permite crear una "vista/búsqueda invertida" en el mapa. Es decir, podemos encontrar una clave por su valor. Esta estructura de datos se denomina mapa bidireccional y, lamentablemente, no es compatible con el JDK. Tanto Apache Common Collections como Guava ofrecen implementaciones de mapas bidireccionales llamadas BidiMap y BiMap, respectivamente. Ambos introducen una restricción que impone un mapeo 1:1 entre claves y valores.7. Copia superficial del mapa
Casi todos, si no todos, los mapas en Java contienen un constructor de copia para otro mapa. Pero el procedimiento de copia no está sincronizado. Lo que significa que cuando un hilo copia un mapa, otro hilo puede cambiar su estructura. Para evitar una desincronización repentina de la copia, se debe utilizar uno de ellos en tal casoCollections.synchronizedMap()
.
Map copiedMap = Collections.synchronizedMap(Map);
Otra forma interesante de copiar superficialmente es utilizar el archivo clone()
. Pero NO lo recomienda ni siquiera el creador del marco de colecciones de Java, Joshua Bloch. En el debate " Copiar constructor versus clonación ", adopta la siguiente posición: Cita: "A menudo proporciono un método de clonación público en clases concretas porque la gente espera que estén allí... es una pena que la clonación no funcione, pero "Ha ocurrido... La clonación es un punto débil y creo que se debería advertir a la gente sobre sus limitaciones". Por esta razón ni siquiera les muestro cómo usar el método clone()
para copiar Mapa
8. Crea un mapa vacío
Si esMap
inmutable, utilice:
Map = Collections.emptyMap();
O utilice cualquier otra realización. Por ejemplo:
Map = new HashMap();
FIN
GO TO FULL VERSION