我有这样的数据结构:
class Parent {
List<Child> children;
}
class Child {
DateTime date;
}
List<Parent> parents = ...
我想找到所有Child
parents
日期时间
我想要一个结果。所有DateTime
及其所有parents
中的最早children
。
List<Parent> parents = create();
List<Child> epp = new ArrayList<Child>();//earliest per parent
parents.forEach(c -> c.getChildren()
.stream()
.min(Comparator.comparing(Child::getDate))
.ifPresent(d -> epp.add(d)));
Optional<Child> earliest = epp.stream()
.min(Comparator.comparing(Child::getDate));
循环每个父项,将每个父项最早添加到epp
列表中,然后循环epp
列表以找到最早的父项。
这是使用Java8实现最简洁/最好的方法吗?
答案 0 :(得分:3)
是的。如果将地图展平为儿童,则无需使用中间列表:
Optional<Child> earliest = parents.stream().
.map(Parent::getChildren).flatMap(List::stream)
.min(Comparator.comparing(Child::getDate));
如果您能够更改Parent
类,那么您可能希望在Parent中添加streamChildren
方法:
class Parent {
public Stream<Child> streamChildren() {
return children.stream();
}
}
这样做的好处是不会让调用者访问基础List
。
顺便说一句,您不需要在原始解决方案中创建自己的ArrayList
。您可以使用:
List<Child> earliest = parents.stream().map(Parent::getChildren)
.map(children -> children.stream().min(Comparator(Child::getDate)))
.filter(Optional::isPresent).map(Optional::get).distinct()
.collect(Collectors.toList());
这避免了'添加'操作的副作用。