Home > Mobile >  Merge/aggregate objects within a list java
Merge/aggregate objects within a list java

Time:12-17

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 SampleObjects 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 ValueObjects in one merged object.

At the end, I need again a list of SampleObjects.

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 SampleObjects. 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 ValueObjects 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 SampleObjects 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())
  • Related