HashMap Java: Guía Completa con Ejemplos Prácticos

HashMap in Java: Guía Completa con Ejemplos Prácticos

La clase HashMap en Java es una estructura de datos fundamental que permite almacenar y recuperar eficientemente datos en forma de pares clave-valor. Esta guía completa te proporcionará una comprensión profunda de la clase HashMap, explorando sus características, funcionalidad y aplicaciones prácticas.

Introducción a HashMap

La clase HashMap en Java implementa la interfaz Map, lo que significa que te permite almacenar colecciones de pares clave-valor. En esencia, la HashMap actúa como un diccionario, donde cada clave debe ser única y se asocia a un valor correspondiente. Si intentas insertar una clave duplicada, el valor asociado a esa clave se reemplazará.

La clase HashMap se encuentra en el paquete java.util y destaca por no estar sincronizada, a diferencia de la clase Hashtable. Esto significa que no es segura para hilos, por lo que debes implementar medidas adicionales de sincronización si necesitas usarla en entornos multihilo. Una de las ventajas de la HashMap es que permite almacenar valores nulos, y admite una sola clave nula. Desde Java 5, se denota como HashMap<K,V>, donde K representa el tipo de la clave y V el tipo del valor. La clase HashMap hereda de la clase AbstractMap e implementa la interfaz Map.

Características de HashMap

La clase HashMap se caracteriza por las siguientes propiedades:

  • Valores basados en claves: La HashMap está organizada en base a una relación clave-valor, donde cada clave es única y se asocia a un valor.
  • Claves únicas: Las claves en una HashMap deben ser únicas. Si se intenta insertar una clave duplicada, se reemplazará el valor asociado a esa clave.
  • Permite valores nulos: La HashMap permite que una clave se asocie a un valor nulo (null). Además, puede contener múltiples valores nulos.
  • No está sincronizada: La HashMap no está sincronizada, lo que significa que no es segura para hilos. Si se utiliza en un entorno multihilo, es necesario implementar medidas adicionales de sincronización.
  • No mantiene el orden: La HashMap no mantiene el orden de inserción de los elementos. La ordenación de los elementos se basa en la implementación interna del algoritmo de hashing.

Estructura de HashMap

Entender la estructura interna de la HashMap es esencial para comprender su funcionamiento:

  • Declaración: public class HashMap extends AbstractMap implements Map, Cloneable, Serializable
  • Parámetros:
    • K: El tipo de las claves.
    • V: El tipo de los valores.
  • Constructores:
    • **HashMap()**: Crea unHashMap` por defecto.
    • HashMap(Map<? extends K,? extends V> m): Inicializa el mapa con los elementos de m.
    • HashMap(int capacity): Inicializa la capacidad del mapa a capacity.
    • HashMap(int capacity, float loadFactor): Inicializa la capacidad y el factor de carga a los valores dados.
LEER:  JSTL Core: Guía Definitiva para la Etiqueta ``

Métodos de HashMap

La clase HashMap proporciona un conjunto completo de métodos para manipular y consultar los elementos almacenados:

Manipulación de elementos

  • `clear(): Elimina todos los elementos del mapa.
  • **isEmpty()**: Devuelvetruesi el mapa está vacío,false` en caso contrario.
  • `clone(): Devuelve una copia del mapa.
  • **entrySet()**: Devuelve un conjunto (Set`) con las entradas del mapa.
  • **keySet()**: Devuelve un conjunto (Set`) con las claves del mapa.
  • put(K key, V value): Inserta un nuevo par clave-valor en el mapa. Si la clave ya existe, se reemplaza el valor asociado.
  • putAll(Map<? extends K,? extends V> m): Inserta todos los elementos del mapa m en el mapa actual.
  • putIfAbsent(K key, V value): Inserta un nuevo par clave-valor si la clave no existe en el mapa.
  • remove(Object key): Elimina el par clave-valor asociado a la clave dada.
  • compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction): Calcula un nuevo valor para la clave dada.
  • computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction): Calcula un nuevo valor para la clave dada solo si la clave no existe en el mapa.
  • computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction): Calcula un nuevo valor para la clave dada solo si la clave existe en el mapa.

Comprobación

  • containsValue(Object value): Devuelve true si el mapa contiene el valor dado, false en caso contrario.
  • containsKey(Object key): Devuelve true si el mapa contiene la clave dada, false en caso contrario.
  • equals(Object o): Compara el mapa actual con otro objeto.
  • forEach(BiConsumer<? super K,? super V> action): Ejecuta una acción para cada entrada del mapa.
  • get(Object key): Devuelve el valor asociado a la clave dada.
  • getOrDefault(Object key, V defaultValue): Devuelve el valor asociado a la clave dada, o el valor por defecto si la clave no está presente.
  • **isEmpty()**: Devuelvetruesi el mapa está vacío,false` en caso contrario.
  • merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction): Combina el valor existente con el valor dado, utilizando la función de combinación dada.
  • replace(K key, V oldValue, V newValue): Reemplaza el valor asociado a la clave dada solo si el valor actual es igual al valor antiguo.
  • replaceAll(BiFunction<? super K,? super V,? extends V> function): Reemplaza todos los valores del mapa utilizando la función dada.
  • **values()**: Devuelve una colección (Collection`) con los valores del mapa.
  • `size(): Devuelve el número de elementos en el mapa.
LEER:  JavaScript GetElementsByClassName(): Selección de Elementos por Clase

Ejemplos Prácticos de HashMap

Veamos ejemplos concretos de cómo utilizar la clase HashMap en Java:

1. Almacenar pares clave-valor

«`java
import java.util.HashMap;

public class HashMapExample {
public static void main(String[] args) {
// Crear un HashMap
HashMap miMapa = new HashMap<>();

    // Insertar elementos
    miMapa.put("Manzana", 1);
    miMapa.put("Plátano", 2);
    miMapa.put("Naranja", 3);

    // Mostrar el mapa
    System.out.println(miMapa); // Salida: {Manzana=1, Plátano=2, Naranja=3}
}

}
«`

2. Insertar elementos con diferentes métodos

«`java
import java.util.HashMap;

public class HashMapExample {
public static void main(String[] args) {
// Crear un HashMap
HashMap miMapa = new HashMap<>();

    // Insertar elementos con put()
    miMapa.put("Nombre", "Juan");
    miMapa.put("Apellido", "Pérez");

    // Insertar elementos con putIfAbsent()
    miMapa.putIfAbsent("Ciudad", "Madrid"); 
    miMapa.putIfAbsent("Nombre", "Ana"); // La clave "Nombre" ya existe, no se modifica

    // Insertar elementos con putAll()
    HashMap<String, String> otroMapa = new HashMap<>();
    otroMapa.put("Edad", "30");
    otroMapa.put("Profesión", "Ingeniero");
    miMapa.putAll(otroMapa);

    // Mostrar el mapa
    System.out.println(miMapa); // Salida: {Nombre=Juan, Apellido=Pérez, Ciudad=Madrid, Edad=30, Profesión=Ingeniero}
}

}
«`

3. Eliminar elementos con diferentes métodos

«`java
import java.util.HashMap;

public class HashMapExample {
public static void main(String[] args) {
// Crear un HashMap
HashMap miMapa = new HashMap<>();
miMapa.put(«Manzana», 1);
miMapa.put(«Plátano», 2);
miMapa.put(«Naranja», 3);

    // Eliminar elementos con remove()
    miMapa.remove("Plátano");

    // Mostrar el mapa
    System.out.println(miMapa); // Salida: {Manzana=1, Naranja=3} 
}

}
«`

4. Reemplazar elementos con diferentes métodos

«`java
import java.util.HashMap;

public class HashMapExample {
public static void main(String[] args) {
// Crear un HashMap
HashMap miMapa = new HashMap<>();
miMapa.put(«Manzana», 1);
miMapa.put(«Plátano», 2);
miMapa.put(«Naranja», 3);

    // Reemplazar elementos con replace()
    miMapa.replace("Manzana", 5); // Reemplaza el valor asociado a la clave "Manzana"

    // Mostrar el mapa
    System.out.println(miMapa); // Salida: {Manzana=5, Plátano=2, Naranja=3}
}

}
«`

Diferencias con otras clases

Es importante comprender las diferencias entre la clase HashMap y otras clases relacionadas:

  • HashSet: La clase HashSet almacena solo valores, mientras que la HashMap almacena entradas clave-valor. La HashSet utiliza un HashMap internamente para su implementación.
  • Hashtable: La clase Hashtable es similar a la HashMap, pero está sincronizada. Esto la hace más segura para hilos, pero también menos eficiente.
  • TreeMap: La clase TreeMap también implementa la interfaz Map, pero mantiene los elementos ordenados por claves. La HashMap no mantiene un orden específico.
LEER:  `this` en JavaScript: La Guía Completa

Ejemplo práctico: Gestión de libros

Veamos un ejemplo práctico de cómo utilizar la HashMap para gestionar una colección de libros:

«`java
import java.util.HashMap;

class Book {
private int id;
private String nombre;
private String autor;
private String editorial;
private int cantidad;

public Book(int id, String nombre, String autor, String editorial, int cantidad) {
    this.id = id;
    this.nombre = nombre;
    this.autor = autor;
    this.editorial = editorial;
    this.cantidad = cantidad;
}

public int getId() {
    return id;
}

public String getNombre() {
    return nombre;
}

public String getAutor() {
    return autor;
}

public String getEditorial() {
    return editorial;
}

public int getCantidad() {
    return cantidad;
}

@Override
public String toString() {
    return "Book{" +
            "id=" + id +
            ", nombre='" + nombre + ''' +
            ", autor='" + autor + ''' +
            ", editorial='" + editorial + ''' +
            ", cantidad=" + cantidad +
            '}';
}

}

public class HashMapBookExample {
public static void main(String[] args) {
// Crear un HashMap para almacenar libros
HashMap biblioteca = new HashMap<>();

    // Agregar libros a la biblioteca
    biblioteca.put(1, new Book(1, "Cien años de soledad", "Gabriel García Márquez", "Editorial Planeta", 10));
    biblioteca.put(2, new Book(2, "El Hobbit", "J.R.R. Tolkien", "Editorial Minotauro", 5));
    biblioteca.put(3, new Book(3, "1984", "George Orwell", "Editorial Planeta", 8));

    // Mostrar la biblioteca
    System.out.println(biblioteca); 

    // Consultar un libro por su ID
    Book libro = biblioteca.get(2);
    if (libro != null) {
        System.out.println("Libro encontrado: " + libro); 
    } else {
        System.out.println("Libro no encontrado.");
    }

    // Eliminar un libro
    biblioteca.remove(3);
    System.out.println("Biblioteca actualizada: " + biblioteca); 
}

}
«`

En este ejemplo, la HashMap biblioteca almacena objetos Book utilizando el ID del libro como clave. Puedes agregar, consultar y eliminar libros de la biblioteca de forma eficiente.

Conclusiones

La clase HashMap en Java es una herramienta fundamental para trabajar con datos en forma de pares clave-valor. Su eficiencia, flexibilidad y facilidad de uso la convierten en una opción ideal para una amplia gama de aplicaciones. Entender sus características, métodos y ejemplos prácticos te permitirá aprovechar al máximo las capacidades de la HashMap en tus proyectos de desarrollo en Java.