2

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.

4
  • I tried to summerize it again. Commented Dec 16, 2022 at 15:22
  • So you have a list of SampleObjects payload and you want to collect ValueObjects that are contained in the lists corresponding to the same id into a single List, and create a new SampleObject based on each aggregated List, right? And the result should be of type List<SampleObject> ? Commented Dec 16, 2022 at 15:52
  • You forget to provide the field name for List<ValueObject> in the SampleObject. Commented Dec 16, 2022 at 15:53
  • The ValueObject just contains some strings. Yes, within the List<SampleObject> are entities that have the same id but different ValueObject. As ValueObject is a list, I want to merge all enteries that have the same id to one SampleObject, this object should contain all ValueObjects of the duplicates. Thank you for your help! Commented Dec 16, 2022 at 16:22

1 Answer 1

1

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())
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you again for the answer but I have a question afterwards, does this change the order of the initial list?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.