Usando Streams con Mapas de Java
En esta entrada de refactorizando, vamos a ver algunos ejemplos de como podemos trabajar usando streams con Mapas de Java, de una manera funcional.
¿Qué es un Stream de Java?
Podríamos definir un Stream de Java como una secuencia de objetos que admiten varios métodos para poder producir el resultado deseado.
Un Stream es una secuencia de objetos que admite varios métodos que se pueden canalizar para producir el resultado deseado.
Teniendo en cuenta la definición anterior, podríamos decir que cualquier colección se podría comportar como una secuencia, ¿pero qué pasa con los Maps. ?, ya que no son secuencia. Veamos la configuración de un Map
Map<String, String> map = new HashMap<>();
Vamos a obtener un Collection de los valores del map
Collection<String> values = map.values();
O también podemos obtener las claves:
Set<String> keySet = map.keySet();
Como acabamos de ver hemos obtenido una secuencia a partir de los valores y las claves de un map. Ahora veamos como podemos obtener un Stream, desde los resultados anteriores:
Stream<String> valuesStream = values.stream(); Stream<String> keysStream = keySet.stream();
Y así de fácil hemos conseguido convertirlo en Stream.
Trabajar con Map’s mediante Streams.
Map a otras estructuras con Stream
Algo que suele suceder bastante frecuente es querer obtener una lista de los valores de un Map que cumplen una determinada condición, vamos a ver un ejemplo de ello.
Para este ejemplo vamos a almacenar en un Map nombres y años:
Map<String, Integer> map = new HashMap<>(); map.put("Pepe",5); map.put("Fran", 8); map.put("Jose", 7); List<String> biggerThanSix = map.entrySet().stream() .filter(e -> 6 < e.getValue()) .map(Map.Entry::getKey) .collect(Collectors.toList())
En las líneas anteriores hemos obtenido una lista a partir del map, en el que la condición es todos aquellos valores que son mayor que seis, por lo que la respuesta sería: Fran y Jose.
En este otro ejemplo vamos a ver como obtener un único valor.
Map<String, Integer> map = new HashMap<>(); map.put("Pepe",5); map.put("Fran", 8); map.put("Jose", 7); Optional<String> biggerThanSix = map.entrySet().stream() .filter(e -> 7< e.getValue()) .map(Map.Entry::getKey) .findFirst();
En el ejercicio anterior, lo que hemos hecho ha sido obtener el primer valor que cumple que es mayor que 7, en este caso nos devolvería un Optional con un String con valor Fran.
Stream a Map
Otras tantas veces podemos tener una lista de objetos que cumplen un patrón y queremos convertirlo a un Map. Veamoslo con un ejemplo:
@Getter @Builder Public class car() { private String model; private int units; }
A partir del objeto anterior vamos a generar una lista de Car. Y convertirla en un map:
public class TestListMap { public static void main(String[] args) { List<Car> cars = new ArrayList<>(); Car car1 = Car.build() .model("Mazda") .units(5) .builder(); Car car2 = Car.build() .model("Seat") .units(5) .builder(); cars.add(car1); cars.add(car2); Map<String, Integer> carsMap = cars.stream().collect( Collectors.toMap(Car::getModel, Car::getUnits)); System.out.println("carsMap: " + carsMap); }
OUTPUT:
carsMap : {Mazda=5, 2=linode.com, Seat=5}
Conclusión
El objetivo del artículo Usando Streams con Mapas de Java, era poder ver como es posible mediante el uso de Stream en java poder convertir en mapas y viceversa, obviamente hay infinidad de posibilidades más, que podéis ir probando.