Suma de valores numéricos en HashMap de Java
Vamos con la primera de las entradas del blog que estaba calentita esperando en el horno: veamos como es la suma de valores numéricos almacenados en un HashMap de Java.
En este punto es necesario comentar que tenemos que conocer la estructura de datos de tipo HashMap en el lenguaje Java y por tanto, ya deberíamos disponer de conocimientos previos del lenguaje, de cierto nivel.
Descripción del problema que debemos solucionar
Este artículo del blog trata de cómo podemos sumar los diferentes valores numéricos que existen en una estructura de datos de tipo HashMap en el lenguaje de programación Java.
Según lo indicado en el párrafo anterior, necesitaremos en primer lugar crear o disponer de una estructura de datos de ese tipo, e inicializarla con valores de tipo numérico. En el ejemplo usaremos datos de tipo double. Las claves nos darán igual porque lo que nos importa son los valores que tienen esas claves y de los que necesitamos su suma.
HashMap miMap = new HashMap();
double total = 0;
double[] suma = {0};
miMap.put("A", 10.0);
miMap.put("B", 20.5);
miMap.put("C", 30.0);
miMap.put("D", 10.5);
miMap.put("E", 40.7);
Primera solución: for-each clásico
Haremos uso de un bucle for-each clásico. Obtenemos los valores con el método .values() del HashMap y vamos incrementando la variable total por cada valor almacenado en el HashMap:
for (double f : miMap.values()) {
total += f;
}
Segunda solución: .streams() y .mapToDouble()
La siguiente solución hace uso de .streams() y .mapToDouble(), lo que evita el uso de bucles. Nuevamente guardamos la suma total en la variable homónima.
Ha sido necesario, obtener un objeto ArrayList (Double porque trabajamos con double) a partir de los valores del HashMap, sobre los que finalmente aplicamos el método .sum():
total = new ArrayList(miMap.values()).stream().mapToDouble(Double::doubleValue).sum();
Tercera solución: streams y map con lambdas
total = miMap.values().stream().mapToDouble(i->i).sum();
Cuarta solución: cambiamos el lambda
Nuevamente optamos por las mismas herramientas de la segunda y tercera solución pero, modificamos el lambda. Tal y como se aprecia, es básicamente el lambda de la anterior solución pero especificamos el tipo de dato de forma explícita:
total = miMap.values().
stream().
mapToDouble(i -> i.doubleValue()).sum();
Cabe notar que en las soluciones dos, tres y cuatro, en realidad usamos el mismo sistema e incluso en la segunda y cuarta, recurrimos a concretar el tipo de valor y en la tercera, se obtiene de forma implícita.
Quinta solución: .forEach()
- Una lambda no debe cambiar el valor de una variable exterior a ésta. De hecho, tal cual, no puede en principio.
- Para conseguirlo, necesitaremos que esa variable sea final o en la práctica así sea. Claro que si es final, no podremos cambiar su valor. ¿Cómo conseguimos esto entonces? Pues mediante un elemento de array. Éste no cambiará pero su valor si. Por esa razón hemos declarado también un array con un sólo elemento.
miMap.forEach((key, value) -> suma[0] += value);
Por tanto, debido a las limitaciones de modificación de un valor de una variable externa a la lambda, hacemos uso de suma[0].
⚠️ Atención ⚠️
Está considerada una mala práctica modificar el valor de una variable externa a una lambda y por ello, en principio no está permitido hacerlo. Se muestra aquí una muestra como ejemplo adicional para resolver el problema planteado en este artículo. Evitaremos su uso por tanto, en la medida de lo posible.✔️ ¡Potencia tu creatividad y convierte tus ideas en realidad con Elementor!
✔️ Diseña sitios web sorprendentes, sin necesidad de conocimientos de programación. Arrastra y suelta elementos, personaliza tu diseño y añade efectos deslumbrantes en cuestión de minutos.
✔️ ¡Impulsa tu presencia en línea y cautiva a tu audiencia con páginas web profesionales y de alto impacto!
✔️ Por si fuera poco, ahora, con la incorporación de inteligencia artificial, podrás generar textos cautivadores de forma automática y sin esfuerzo.
💰 💰 💰 Y si lo que quieres es ganar dinero, hazte afiliado y consigue ¡jugosas comisiones!💰 💰 💰
Finalmente, el código completo del ejemplo
Veamos ahora el código con las soluciones o ejemplos al completo. ¿Existen otras formas? Pues sí pero me centro en las más usadas que además ofrecen una serie de detalles interesantes para aprender.
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.DoubleStream;
public class Main {
public static void main(String[] args) {
HashMap miMap = new HashMap();
double total = 0;
double[] suma = {0};
miMap.put("A", 10.0);
miMap.put("B", 20.5);
miMap.put("C", 30.0);
miMap.put("D", 10.5);
miMap.put("E", 40.7);
for (double f : miMap.values()) {
total += f;
}
System.out.println("Con un bucle normal: " + total);
total = new ArrayList(miMap.values()).stream().mapToDouble(Double::doubleValue).sum();
System.out.println("Con mapToDouble: " + total);
total = miMap.values().stream().mapToDouble(i->i).sum();
System.out.println("Con mapToDouble y lambda 1: " + total);
total = miMap.values().
stream().
mapToDouble(i -> i.doubleValue()).sum();
System.out.println("Con mapToDouble y lambda 2: " + total);
miMap.forEach((key, value) -> suma[0] += value);
System.out.println("Con forEach: " + total);
}
}
Conclusión
Un artículo más orientado en esta ocasión a personas con conocimientos previos.
Finalizamos. Un cordial saludo y hasta otra.