Search code examples
javajava-streamgroupingarray-merge

java stream How to merge same value to list


My entity is

private String subject;
private String unit1;  
private String unit2;  
private String unit3;  

List<entity> getList = repo.findAll();

"getList" show this list my controller return this value

 [
        {
          "unit1": "wert",
          "unit2": "2",
          "unit3": "6",
          "subject": "grdg"
        },
        {
          "unit1": "sdfg",
          "unit2": "2",
          "unit3": "e",
          "subject": "gdsg4"
        },
        {
          "unit1": "sdfg",
          "unit2": "3",
          "unit3": "hrh",
          "subject": "g4ds"
        },
        {
          "unit1": "qwer",
          "unit2": "4",
          "unit3": "rh5",
          "subject": "g4e"
        },
        {
          "unit1": "asdf",
          "unit2": "5",
          "unit3": "erty",
          "subject": "asdf"
        },
    {
      "unit1": "zxcv",
      "unit2": "2",
      "unit3": "3",
      "subject": "asdf"
    }
  ]

and i want to merge same subject

{asdf:[{"unit1": "wert",
      "unit2": "2",
      "unit3": "6"},{ "unit1": "zxcv",
      "unit2": "2",
      "unit3": "3"}],
g4e:[{
          "unit1": "qwer",
          "unit2": "4",
          "unit3": "rh5"}]
        }
}

I mean i want to merge like this

{ subject_name:[other_data]}

getList.stream.collect(Collectors.groupingBy(Subject::getSubject)).values().stream().collect(Collectors.toList());

that code merge is right?


Solution

  • Sufficient code to groupBy is to not extract values out of the grouped Map so as you are left with a mapping of each subject to its corresponding List of entities.

    Map<String, List<Subject>> subjectMap = getList.stream()
            .collect(Collectors.groupingBy(Subject::getSubject));
    

    Further, when you want to map the elements of the List<Subject> to another view type, you can perform a mapping operation as:

    Map<String, List<Wrapper>> subjectMap = getList.stream()
            .collect(Collectors.groupingBy(Subject::getSubject,
                    Collectors.mapping(Wrapper::extractAttributes,
                            Collectors.toList())));
    

    with an additional class defined as(or you could have chosen to mutate the existing Subject class as well):

    @Builder
    static class Wrapper {
        private String unit1;
        private String unit2;
        private String unit3;
    
        public static Wrapper extractAttributes(Subject subject) {
            return Wrapper.builder().unit1(subject.getUnit1())
                    .unit2(subject.getUnit2())
                    .unit3(subject.getUnit3()).build();
        }
    }