JavaRush /Blog Java /Random-ES /Las 9 preguntas principales sobre mapas en Java
Treefeed
Nivel 21

Las 9 preguntas principales sobre mapas en Java

Publicado en el grupo Random-ES
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 .Las 9 preguntas principales sobre mapas en Java - 1

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étodo addAll(). 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 SortedMapes TreeMap . Su constructor acepta un comparador. El siguiente código muestra cómo convertir uno normal Mapen 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 usar Entry.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 SortedMapen 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 inicializador static(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 TreeMapordenará todos los valores en el "orden natural" de las claves o mediante un comparador.
  • Pares clave-valor válidos. HashMaple permite tener una clave nula y un valor nulo. HashTableno permite una clave nula o un valor nulo. Si TreeMapse utiliza el orden natural o el comparador no permite una clave nula, se generará una excepción.
  • Sincronización . Solo HashTablesincronizados, el resto no. Pero "si no se necesita una implementación segura para subprocesos, se recomienda utilizar " HashMapen su lugar HashTable.
Comparación más detallada
.                       | 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 caso Collections.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 es Mapinmutable, utilice:
Map = Collections.emptyMap();
O utilice cualquier otra realización. Por ejemplo:
Map = new HashMap();
FIN
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION