Reputation: 21978
I have a very long stream of children.
// ordered by parent.id / child.id
Stream<Child> childStream;
say,
Child(id = 1, parent(id = 1))
Child(id = 2, parent(id = 1))
Child(id = 3, parent(id = 2))
Child(id = 4, parent(id = 2))
Child(id = 5, parent(id = 3))
Each Child
has a parent.
class Child {
Parent parent;
}
Now, how can I map the stream into a stream of Family
?
class Family {
Parent parent;
List<Child> children;
}
I already know Collectors.groupingBy
, but the stream is so long that collecting them all into a Map
is not applicable.
Upvotes: 3
Views: 99
Reputation: 637
Here is the solution by StreamEx if the stream is ordered by parent(id).
StreamEx.of(childStream)
.collapse((a, b) -> a.getParent().getId() == b.getParent().getId(), Collectors.toList())
.map(cl-> new Family(cl.get(0).getParent(), cl))...;
collapse
is lazy evaluation comparing groupBy
. For Example, if you only want to get first 5 families, only the children in first 5 families will be loaded, not all.
StreamEx.of(childStream)
.collapse((a, b) -> a.getParent().getId() == b.getParent().getId(), Collectors.toList())
.map(cl-> new Family(cl.get(0).getParent(), cl))
.limit(5);
Upvotes: 1
Reputation: 393771
In order to group your Child
instances into Family
instances, you must process the Stream
, so a terminal operation is required. You can use groupingBy
and then transform the resulting Map
into the Stream
you need:
Stream<Family> families =
childStream.collect(Collectors.groupingBy(Child::getParent))
.entrySet()
.stream()
.map(entry -> new Family(entry.getKey(),entry.getValue()));
This is assuming your Family
class has a Family(Parent parent, List<Child> children)
constructor.
Upvotes: 6