My goal is to expand List<A>
, where each A
has an attribute List<B>
to a List<A>
, where each A
will contain a list with a single distinct object B
.
Considering A
and B
have this structure:
class A{
String idA;
List<B> listOfB;
}
class B{
Long idB;
String name;
}
I'd like to expand the List<A>
so that it contains an object A
for each distinct contained object B
(where two objects B
are differentiated by the attribute name
).
For example
[
{
"idA": 1,
"listOfB": [
{
"idB": 3,
"name": "Foo"
}
]
},
{
"idA": 2,
"listOfB": [
{
"idB": 3,
"name": "Foo"
},
{
"idB": 4,
"name": "Bar"
}
]
}
]
should be transformed to
{
"idA": 1,
"listOfB": [
{
"idB": 3,
"name": "Foo"
}
]
},
{
"idA": 2,
"listOfB": [
{
"idB": 3,
"name": "Foo"
}
]
},
{
"idA": 2,
"listOfB": [
{
"idB": 4,
"name": "Bar"
}
]
}
]
How can I do this using streams?
CodePudding user response:
If you implement equals in B, this could be one of the solution.
Set<B> bs = as.stream()
.map(A::getListOfB)
.flatMap(List::stream)
.collect(Collectors.toSet());
return bs.stream()
.map(s -> as.stream()
.filter(a -> a.getListOfB().contains(s))
.map(a -> new A(a.idA, List.of(s)))
.collect(Collectors.toList())
)
.flatMap(List::stream)
.collect(Collectors.toList());
Please note I have created all param constructor in both A & B.
CodePudding user response:
If I understood correctly your explanation and example you've provided, you need to build a resulting list comprised of objects A
, where each element will hold a reference to a list with one element of type B
.
A singleton-list and a new object A
that will hold this list have to be created for every distinct object B
initially contained in a particular object A
.
For that, you can use a flatMap()
operation, which takes an element and returns a stream of flattened elements. Operation distinct()
applied in the nested stream will ensure that only unique objects B
will be peeked from each list (I assume that hashCode/equals
contract was correctly implemented in the class B
).
List<A> listB = getSourceList();
listB.stream()
.flatMap(a -> a.getListOfB().stream()
.distinct()
.map(b -> new A(a.getIdA(), List.of(b))))
.collect(Collectors.toList());