地图<;字符串,Map<;字符串,Car>&燃气轮机;列出<;汽车>;使用Java8

地图<;字符串,Map<;字符串,Car>&燃气轮机;列出<;汽车>;使用Java8,java,java-8,flatten,Java,Java 8,Flatten,假设我有标题中描述的结构: Map<String, Map<String, Car>> mapNeighborhood 地图地图邻居 包含一个邻居中的所有汽车,分别按地址和车牌索引。 我想选择所有红色的车,把它们重新漆成黑色。为了完成这项任务,我尝试使用Java8“展开”这两个映射并获得一个列表。一旦我得到了这个列表,应用一个谓词,我就可以只选择红色的汽车并应用重新绘制 List<Car> listCars = new ArrayList<Car&g

假设我有标题中描述的结构:

Map<String, Map<String, Car>> mapNeighborhood
地图地图邻居
包含一个邻居中的所有汽车,分别按地址和车牌索引。 我想选择所有红色的车,把它们重新漆成黑色。为了完成这项任务,我尝试使用Java8“展开”这两个映射并获得一个列表。一旦我得到了这个列表,应用一个谓词,我就可以只选择红色的汽车并应用重新绘制

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));
List listCars=new ArrayList();
MapNeighborary.values().forEach(映射->映射.values())
.forEach(car->listCars.add(car));
listCars.stream().filter(Car::isRed)
.forEach(car->car.repaint(Color.Black));
我确信,在Java8中,只需使用一行代码就可以实现同样的效果,但我认为可能会丢失可读性


我的问题是:是否有另一种不那么冗长的方法将地图平铺成列表?可能使用
flatMap
。提前感谢。

您不需要中间
列表

mapNeighborhood.values().stream()
                        .flatMap(byPlate -> byPlate.values().stream())
                        .filter(Car::isRed)
                        .forEach(car -> car.repaint(Color.Black))
我认为这比您的代码可读性更强,而且更短。客观上,它在时间和空间上都更加有效


还请注意,
Car::isRed
有些奇怪,因为您需要检查
Car
上所有可能的
Color
-为季节添加新的
Color
,重新实施
Car

Color::isRed
更有意义,使用
Car
实现
Colored
或类似工具

interface Colored {
    Color getColor();
}

// in Color
public static boolean isRed(Colored colored) {
    return Objects.equals(colored.getColor(), RED);
}

我的结果与@Boris相同,但我将向您展示如何使用IntelliJ实现这一点:

for (Map<String, Car> value : mapNeighborhood.values()) {
    for (Car car : value.values()) {
        if (car.isRed()) {
            car.repaint(Color.BLACK);
        }
    }
}
对于任何类型的循环,您都可以尝试使用IntelliJ来帮助您智能地转换为Java8样式

List<Car> collect = mapNeighborhood.values().stream()
                                            .map(Map::values)
                                            .flatMap(Collection::stream)
                                            .collect(Collectors.toList());
List collect=mapNeighborhood.values().stream()
.map(映射::值)
.flatMap(集合::流)
.collect(Collectors.toList());
然后,您可以继续操作汽车列表。

这会很有帮助

mapNeighborhood.values().stream()
                        .map(Map::values)
                        .flatMap(Collection::stream)
                        .filter(car -> car.getColor().equalsIgnoreCase("red"))
                        .forEach(car -> car.repaint("black"));

你说得对,你的解决方案完全可读,而且比我的更有效。:-)这就是我要找的。我觉得我的太冗长和无能了。我真正的课程不是汽车,这不是家庭作业,方法汽车::isRed只是一个比喻,但我会把你所说的保留在我的课堂上。非常感谢你!好把戏!我使用Eclipse,我不熟悉IntelliJ,但我喜欢你的答案。谢谢<代码>映射邻域.values().forEach(value->value.values().forEach(car->rePiantIfRed(car))@HadiJ好吧,这几乎是我最初的解决方案,但将过滤隐藏在方法“repaintfred”中。谢谢你的评论。@HadiJ我已经用你的方法删除了一个多余的流()。谢谢:-)
mapNeighborhood.values().stream()
                        .map(Map::values)
                        .flatMap(Collection::stream)
                        .filter(car -> car.getColor().equalsIgnoreCase("red"))
                        .forEach(car -> car.repaint("black"));