假设我有标题中描述的结构:
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。提前谢谢。
发布于 2019-05-14 06:06:54
你不需要中间的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);
}发布于 2019-05-14 06:22:13
我的结果在鲍里斯身上是一样的,但我将向您展示如何用IntelliJ实现它:
for (Map<String, Car> value : mapNeighborhood.values()) {
for (Car car : value.values()) {
if (car.isRed()) {
car.repaint(Color.BLACK);
}
}
}然后将光标移动到第一个"for“字中,按Alt-Enter,然后选择”用ForEach替换“,tada,我们开始:
mapNeighborhood.values().stream()
.flatMap(value -> value.values().stream())
.filter(Car::isRed)
.forEach(car -> car.repaint(Color.BLACK));使用任何类型的循环,您都可以尝试使用IntelliJ来帮助您智能地转换为java 8样式。
发布于 2019-05-14 06:48:55
这是我试过的一种方法
List<Car> collect = mapNeighborhood.values().stream()
.map(Map::values)
.flatMap(Collection::stream)
.collect(Collectors.toList());然后你就可以继续操作汽车的列表了。
https://stackoverflow.com/questions/56123855
复制相似问题