javacollectionsjava-8java-stream

Grouping by object - Java streams


I have a list of data like the one given below:

List<Data> data = new ArrayList<Data>();
data.add(new Data("d1", "option1"));
data.add(new Data("d2", "option1"));
data.add(new Data("d1", "option2"));
data.add(new Data("d3", "option1"));
data.add(new Data("d3", "option2"));
data.add(new Data("d3", "option3"));

The structure looks like this:

class Data {
    private String name;
    private String option;
    private List<String> options = new ArrayList<>();
    public Data(String name, String option) {
        this.name = name;
        this.option = option;
    }

    public void addOption(String option) {
        options.add(option);
    }
}

How to group the items to a new array based on the name with its options,

[
"d1": {
    "name": "d1",
    "options": ["option1", "option2"]
},
"d2": {
    "name": "d2",
    "options": ["option1"]
},
"d3": {
    "name": "d3",
    "options": ["option1", "option2", "option3"]
}
]

Solution

  • You can use a Collectors.toMap collector:

    Map<String,Data>
        grouped = data.stream()
                      .collect(Collectors.toMap(Data::getName,
                                                d -> new Data(d.getName(),d.getOption()),
                                                (d1,d2) -> {d1.addOptions(d2.getOptions()); return d1;});
    

    This will require changing the Data constructor to add the passed option to the options List as well as adding an addOptions method that receives a list of options and adds all of them to the options List of the current instance.