Ejemplo de uso de HashMap en Java

En esta ocasión voy a compartir un ejemplo en el que se ve como utilizar tablas hash en Java mediante la clase HashMap.

Imaginemos que necesitamos una aplicación para una tienda mediante la que queremos almacenar los distintos productos que venderemos y el precio que tendrán. Y se quiere que tenga las funciones básicas, introducir un elemento, modificar su precio, eliminar un producto y mostrar los productos que tenemos con su precio.

Vamos con la resolución del ejemplo de HashMap en Java. En primer lugar para hacerlo sencillo hacemos una aplicación para consola y con unos pocos System.out.println y la clase Scanner para leer desde teclado se crea un sencillo menú con las posibles opciones y con un switch se llama a las distintas funciones para tratar el HashMap.


public static void main(String[] args) {

    HashMap<String,Float> listaProductos = new HashMap<String,Float>();
    Scanner sc = new Scanner(System.in);
    int opcionElegida = 0;
    float precio;
    String codigo;

    while (opcionElegida != 5) {
        System.out.println("Introduce el numero de la opción que quieras:");
        System.out.println("1.- Introducir producto");
        System.out.println("2.- Modificar precio");
        System.out.println("3.- Mostrar todos los productos");
        System.out.println("4.- Eliminar producto");
        System.out.println("5.- Salir");
        opcionElegida = sc.nextInt();

        switch (opcionElegida) {
            case 1:
                System.out.println("Introduce el códido del producto:");
                codigo = sc.next();
                System.out.println("Introduce el precio del producto:");
                precio = sc.nextFloat();
                guardarProducto(codigo, precio, listaProductos);
                break;
            case 2:
                System.out.println("Introduce el códido del producto del que quieres cambiar el precio:");
                codigo = sc.next();
                modificaPrecio(codigo, listaProductos);
                break;
            case 3:
                mostrarProductos(listaProductos);
                break;
            case 4:
                System.out.println("Introduce el códido del producto que quieres eliminar:");
                codigo = sc.next();
                eliminaProducto(codigo, listaProductos);
                break;
            case 5:
                break;   // Si la opcion es 5 no se hace nada 
            default:
                System.out.println("Tienes que introducir una opción valida");
        }

    }
}

Usamos métodos estáticos para no tener que instanciar ningún objeto y ahorrarnos llamar a las funciones desde un objeto porque para lo sencillo que es el ejemplo no tiene sentido crear por ejemplo una clase tienda y ponerle esos métodos o por lo menos es tan innecesario como que las operaciones de la clase Math tampoco fuesen estáticas.

Empezamos con la función que guarda un nuevo producto, es decir, que añade un nuevo elemento al HashMap. Primero comprobamos que no halla ningún elemento con el código introducido y si es así añadimos el elemento con la función HashMap.put(clave,contenido).


public static void guardarProducto(String codigo, float precio, HashMap <String,Float> listaProductos){
    if (listaProductos.containsKey(codigo)) {
        System.out.println("No se puede introducir el producto. El código esta repetido.");
    } else {
        listaProductos.put(codigo, precio);               
    }
}

La función para modificar un elemento es prácticamente igual que la anterior pero, la función HashMap.put(clave,contenido) en esta ocasión se ejecutara cuando se encuentre algún elemento con la clave pasada. Como se puede ver la función put(clave,valor) añade un nuevo elemento si la clave no esta repetida y modifica el elemento con la clave pasada si ya había un elemento con esa clave.


public static void modificaPrecio(String codigo, HashMap<String,Float> listaProductos){
    Scanner sc = new Scanner(System.in);
    if (listaProductos.containsKey(codigo)) {
        System.out.println("Introduce el precio del producto:");
        listaProductos.put(codigo, sc.nextFloat());            
    } else {
        System.out.println("No hay ningun producto con ese código.");
    }
}

La función encargada de mostrar los productos es la que tiene quizás un poco más de dificultad a priori porque para recorrer una hashMap no hay índices como en los arrays o ArrayList y es necesario usar un iterador para recorrer el Hashmap.

Vamos a ver las 2 formas de recorrer un Hashmap en Java, usando entrySet() o usando keySet().

Con keySet() lo que se obtiene como indica el nombre de la función son las claves y mediante un iterador se recorre la lista de claves. De esta forma si queremos saber también el valor de cada elemento tenemos que usar la función get(clave).


public static void mostrarProductos(HashMap<String, Float> listaProductos) {
    String clave;
    Iterator<String> productos = listaProductos.keySet().iterator();
    System.out.println("Hay los siguientes productos:");
    while(productos.hasNext()){
        clave = productos.next();
        System.out.println(clave + " - " + listaProductos.get(clave));
    }        
}

La otra opción es entrySet() con la que se obtienen los elementos enteros y al igual que en el caso anterior con un iterador se recorre el hashMap, pero de esta forma hay que crear una variable de tipo Map.Entry para almacenar el elemento y con los métodos getKey() y getValue() de Map.Entry se obtienen los valores. Nota: Se puede usar un iterador del tipo que vamos a cojer en este caso Map.Entry de la misma forma que se hizo en el método anterior, o sino usar un iterador genérico y luego hacer el casting a Map.Entry.


public static void mostrarProductos2(HashMap<String, Float> listaProductos) {
    Iterator iterador = listaProductos.entrySet().iterator();
    //Iterator<Map.Entry<String, Float>> iterador = listaProductos.entrySet().iterator();
    Map.Entry producto;
    while (iterador.hasNext()) {
        producto = (Map.Entry) iterador.next();
        //producto = iterador.next(); Si se usase tambien la otra linea comentada.
        System.out.println(producto.getKey() + " - " + producto.getValue());
    } 
}

Con esta segunda forma es necesario usar una variable Map.Entry y realizar el import pertinente, pero el resultado es el mismo y el numero de líneas de código es igual, aunque esta segunda forma supongo que sea más eficiente puesto que mientras que en la primera solo obtenemos la clave y luego hay que buscar el contenido asociado con la función get(clave) con esta segunda forma ya tenemos ambos valores y no hay que realizar esa búsqueda adicional, aunque quizás la primera forma sea mas «sencilla».

Y finalmente la función para eliminar un producto, en la que primero comprobamos que exista un elemento con la clave pasada y si es así se elimina con la función remove(clave).


public static void eliminaProducto(String codigo, HashMap<String,Float> listaProductos) {
    if (listaProductos.containsKey(codigo)) {
        listaProductos.remove(codigo);
    } else {
        System.out.println("No hay ningun producto con ese código.");  
    }       
}