我是Java 8的新手,我需要重写一段旧代码来实现新的算法。 任务是过滤每个列表具有最大速度的对象。 列表嵌套在地图内部:道路的根地图,其中包含路段的地图,每条路段的地图都包含一系列对象,每个对象描述一个时间间隔的测得速度。我需要找到每个列表的所有最大速度。
我找到了以下链接,这些链接看起来像我的问题,但是我无法适应它们,而且我不确定我的尝试是否能正确解决我的问题。
How do you filter nested loops using Java 8 streams and filters?
Java 8 Filter Map<String,List<Employee>>
这是我作为示例编写我的代码
Map<String, Map<String, Employee>> employeeMap =
employeeMap.entrySet()
.stream()
.collect(toMap(Map.Entry::getKey,
e -> e.getValue().entrySet().stream()
.filter(emp -> !emp.getValue().getState().equals("MI"))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue))));
for(Car car : cars) {
for (Engine engine : car.getEngines()) {
for (Part part : engine.getParts()) {
// ...
}
}
}
cars.stream()
.flatMap(car -> car.getEngines().stream())
.flatMap(engine -> engine.getParts().stream())
.forEach(part -> { ... });
这是我生成的代码
Map<Integer, Map<Integer, List<PartialSpeed>>> speedsPerRoadPerSegment;
ArrayList<PartialSpeed> maxSpeedPerSegment = new ArrayList<PartialSpeed>();
speedsPerRoadPerSegment.entrySet().stream()
.forEach(road-> road.getValue().entrySet()
.stream()
.forEach(segment ->
{
Optional<PartialSpeed> result = segment.getValue().stream()
.max(Comparator.comparing(PartialSpeed::getnVelFfs));
maxSpeedPerSegment.add(result.get());
}));
我坚持该示例的所有尝试都存在无法识别结果类型的问题。 这是我能够达到的最佳效果(不起作用):
speedsPerRoadPerSegment.entrySet().stream()
.flatMap(road-> road.getValue().entrySet()
.stream().flatMap(
segment -> segment .getValue()
.stream()
.max(Comparator.comparing(PartialSpeed::getnVelFfs))
));
如您所见,我刚刚用foreaches替换了旧的for循环。我想了解如何直接从lambda表达式中获取最大元素列表。
答案 0 :(得分:6)
通常,无论您使用循环还是流,在处理Map
时,都应选择正确的集合视图keySet()
,entrySet()
或values()
,具体取决于您实际需要哪些元素。由于您只对值感兴趣,因此请勿使用entrySet()
。
然后,将正确的终端操作应用于流,以获得最终结果:
List<PartialSpeed> maxSpeedPerSegment =
speedsPerRoadPerSegment.values().stream()
.flatMap(m -> m.values().stream())
.map(list -> Collections.max(list, Comparator.comparing(PartialSpeed::getnVelFfs)))
.collect(Collectors.toList());
此方法使用Collections.max
而不是嵌套的Stream操作,如果集合为空,它将抛出异常(就像无条件调用get()
上的Optional
一样)。
如果可能出现空列表,则可以事先对其进行过滤:
List<PartialSpeed> maxSpeedPerSegment =
speedsPerRoadPerSegment.values().stream()
.flatMap(m -> m.values().stream())
.filter(list -> ! list.isEmpty())
.map(list -> Collections.max(list, Comparator.comparing(PartialSpeed::getnVelFfs)))
.collect(Collectors.toList());