【问题标题】:Map<String, Map<String, Car>> to List<Car> using Java 8使用 Java 8 将 <String, Map<String, Car>> 映射到 List<Car>
【发布时间】:2019-10-01 02:14:28
【问题描述】:

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

Map<String, Map<String, Car>> mapNeighborhood

包含分别按地址和车牌索引的社区中的所有汽车。 我想选择所有红色汽车以将它们重新涂成黑色。为了完成这项任务,我尝试使用 Java 8 将这两个地图“扁平化”并获得一个列表。获得列表后,应用谓词我可以只选择红色汽车并应用重绘。

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));

我确信您可以在 Java 8 中仅使用一行代码实现相同的效果,但我认为您可能会失去可读性。

我的问题是:还有另一种不那么冗长的方法可以将地图展平为列表吗?也许使用flatMap。提前致谢。

【问题讨论】:

  • mapNeighborhood.values().forEach(value-&gt;value.values().forEach(car -&gt; rePiantIfRed(car)));
  • @HadiJ 好吧,这几乎是我最初的解决方案,但将过滤隐藏在方法“repaintIfRed”中。无论如何感谢您的评论。
  • @HadiJ 我已经删除了一个多余的 stream() 应用你的方法。谢谢:-)

标签: java java-8 flatten


【解决方案1】:

您不需要中间人List

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);
}

【讨论】:

  • 你是对的,你的解决方案比我的解决方案可读性强,效率更高。 :-) 这就是我想要的。我觉得我的太冗长和效率低下。我真正的课程不是 Car,这不是家庭作业,方法 Car::isRed 只是一个比喻,但我会保留你所说的。非常感谢!
【解决方案2】:

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

for (Map<String, Car> value : mapNeighborhood.values()) {
    for (Car car : value.values()) {
        if (car.isRed()) {
            car.repaint(Color.BLACK);
        }
    }
}

然后你将光标移到第一个“for”字上,按 Alt-Enter 然后选择“Replace with ForEach”,tada,我们开始:

mapNeighborhood.values().stream()
                        .flatMap(value -> value.values().stream())
                        .filter(Car::isRed)
                        .forEach(car -> car.repaint(Color.BLACK));

任何类型的循环,你都可以尝试使用 IntelliJ 来帮助你智能地转换为 java 8 风格

【讨论】:

  • 好招!我使用 Eclipse,但我不熟悉 IntelliJ,但我喜欢你的回答。谢谢!
【解决方案3】:

这是我尝试过的一种方法

List<Car> collect = mapNeighborhood.values().stream()
                                            .map(Map::values)
                                            .flatMap(Collection::stream)
                                            .collect(Collectors.toList());

然后您可以继续操作汽车列表。

【讨论】:

    【解决方案4】:

    这会很有帮助。

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

    【讨论】:

      猜你喜欢
      • 2018-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-25
      • 2020-03-17
      • 2019-11-27
      • 1970-01-01
      相关资源
      最近更新 更多