Reputation: 664
I have a data structure like this:
class Parent {
List<Child> children;
}
class Child {
DateTime date;
}
List<Parent> parents = ...
I want to find the earliest Child
DateTime in all the parents
I want one result. The earliest DateTime
across all the parents
and all their 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));
Loop each parent, add the earliest per parent into the epp
list, and then I loop the epp
list to find the actual earliest.
Is this the most concise / best way to achieve with Java8?
Upvotes: 3
Views: 2410
Reputation: 27976
Yes there is. You don't need to use the intermediate list if you flatten the map to children:
Optional<Child> earliest = parents.stream().
.map(Parent::getChildren).flatMap(List::stream)
.min(Comparator.comparing(Child::getDate));
If you are able to change the Parent
class then you might want to add a streamChildren
method in Parent:
class Parent {
public Stream<Child> streamChildren() {
return children.stream();
}
}
This has the advantage of not giving the caller access to the underlying List
.
As an aside, you didn't need to create your own ArrayList
in the original solution. You could have used:
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());
That avoids the side effect of the 'add' operation.
Upvotes: 3