Let's say that I have the structure described in the title:
Map<String, Map<String, Car>> mapNeighborhood
that contains all cars in a neighborhood indexed by address and plate respectively. I want to select all red cars to repaint them in black. To accomplish that task, I have tried to "flat" both Maps and obtain a List using Java 8. Once I got the List, applying a Predicate I can select only the red cars and apply the repainting.
List<Car> listCars = new ArrayList<Car>();
mapNeighborhood.values().forEach(map -> map.values()
.forEach(car -> listCars.add(car)));
listCars.stream().filter(Car::isRed)
.forEach(car -> car.repaint(Color.Black));
I'm sure that you can achieve the same using just one line in Java 8, but I think that you may lose legibility.
My question is: Is there another less verbose way of flattening the Maps into a List? Maybe using flatMap
. Thanks in advance.
You don't need an intermediate List
mapNeighborhood.values().stream()
.flatMap(byPlate -> byPlate.values().stream())
.filter(Car::isRed)
.forEach(car -> car.repaint(Color.Black))
I think this is both more readable than your code and shorter. It is also objectively much more efficient, both in time and space.
Also note that Car::isRed
is somewhat odd as you would need a check for every possible Color
on Car
- add a new color
for the season, reimplement Car
.
Color::isRed
makes much more sense, with Car
implements Colored
or some such
interface Colored {
Color getColor();
}
// in Color
public static boolean isRed(Colored colored) {
return Objects.equals(colored.getColor(), RED);
}