使用 Java 8 映射<String, Map<String, Car>> 到列表<Car>
Map<String, Map<String, Car>> to List<Car> using Java 8
假设我有标题中描述的结构:
Map<String, Map<String, Car>> mapNeighborhood
其中包含分别由地址和车牌索引的社区中的所有汽车。
我想 select 将所有红色汽车重新涂成黑色。为了完成该任务,我尝试 "flat" 两个地图并使用 Java 8 获取列表。一旦我获得列表,应用谓词我可以 select 仅红色汽车并应用重绘。
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
。提前致谢。
你不需要中级 List
mapNeighborhood.values().stream()
.flatMap(byPlate -> byPlate.values().stream())
.filter(Car::isRed)
.forEach(car -> car.repaint(Color.Black))
我认为这比您的代码更可读,而且更短。它在客观上 更 更有效,无论是时间还是 space。
另请注意,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);
}
}
}
然后将光标移动到第一个 "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样式
这是我试过的一种方法
List<Car> collect = mapNeighborhood.values().stream()
.map(Map::values)
.flatMap(Collection::stream)
.collect(Collectors.toList());
然后您可以继续操作汽车列表。
这很有用。
mapNeighborhood.values().stream()
.map(Map::values)
.flatMap(Collection::stream)
.filter(car -> car.getColor().equalsIgnoreCase("red"))
.forEach(car -> car.repaint("black"));
假设我有标题中描述的结构:
Map<String, Map<String, Car>> mapNeighborhood
其中包含分别由地址和车牌索引的社区中的所有汽车。 我想 select 将所有红色汽车重新涂成黑色。为了完成该任务,我尝试 "flat" 两个地图并使用 Java 8 获取列表。一旦我获得列表,应用谓词我可以 select 仅红色汽车并应用重绘。
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
。提前致谢。
你不需要中级 List
mapNeighborhood.values().stream()
.flatMap(byPlate -> byPlate.values().stream())
.filter(Car::isRed)
.forEach(car -> car.repaint(Color.Black))
我认为这比您的代码更可读,而且更短。它在客观上 更 更有效,无论是时间还是 space。
另请注意,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);
}
}
}
然后将光标移动到第一个 "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样式
这是我试过的一种方法
List<Car> collect = mapNeighborhood.values().stream()
.map(Map::values)
.flatMap(Collection::stream)
.collect(Collectors.toList());
然后您可以继续操作汽车列表。
这很有用。
mapNeighborhood.values().stream()
.map(Map::values)
.flatMap(Collection::stream)
.filter(car -> car.getColor().equalsIgnoreCase("red"))
.forEach(car -> car.repaint("black"));