I have a custom type which looks like this:
public class SampleObject {
private UUID id;
private List<ValueObject> values;
// getters, all-args constructor, etc.
}
The ValueObject
just contains some Strings.
And I have a List
of SampleObject
s payload
. Within that list, there are several objects with the same id
but different values in the List<ValueObject>
.
What I want to archive is to merge all objects with the same id
and add all the different lists of the ValueObject
s in one merged object.
At the end, I need again a list of SampleObject
s.
What I tried is the following:
List<SampleObject> payload = // initializing the List
payload.stream().collect(Collectors.groupingBy(SampleObject::getId));
But this returns a Map
of List
of SampleObject
s.
And I don't know how to merge then the objects under the value of this Map.
CodePudding user response:
Collectors.flatMapping()
In order to combine together and store into a single list all the ValueObject
s that correspond to the same id
you can use Collector flatMapping()
, which expects a function that produces a Stream from the element (similarly to flatMap()
operation) and a downstream Collector which tells how the new elements produced by the function need to be stored.
A combination of Collectors groupingBy()
and flatMapping()
would give you a map of type Map<UUID, List<ValueObject>>
. To produce a List
of SampleObject
s out of it, you can create a stream map entries, transform each entry into a SampleObject
and then collect the elements into a List.
That's how implementation might look like:
List<SampleObject> payload = // initializing the list
List<SampleObject> mergedData = payload.stream()
.collect(Collectors.groupingBy( // intermediate Map<UUID, List<ValueObject>>
SampleObject::getId,
Collectors.flatMapping(
sampleObject -> sampleObject.getValues().stream(),
Collectors.toList()
)
))
.entrySet().stream()
.map(entry -> new SampleObject(entry.getKey(), entry.getValue()))
.toList(); // for Java 16 or collect(Collectors.toList())