Question: I have a list of objects `List<WorkingActivityModel> mList = new ArrayList<>();`

```
public class WorkingActivityModel {
   private String name;
   private Sales sales;
   private Shifts shifts;
}

```

The Sales model is:

```
public class Sales {
    private int product1;
    private int product2;
}

```

The Shifts model is:

```
public class Shifts {
    private int shift1;
    private int shift2;
}

```

How can I group items in `List<WorkingActivity> mList` by name and then sum corresponding sales and shifts? So if I have 2 items in the list with the same name then group them and sum its sales and shifts?

I have tried stream but with no success:

```
List<WorkingActivityModel> result = mList.stream()
                        .collect(groupingBy(WorkingActivityModel::getName, LinkedHashMap::new, toList()))
                        .values().stream()
                        .flatMap(Collection::stream)
                        .collect(toList());

```

Another option is:

```
List<WorkingActivity> mList = new ArrayList<>();

HashMap<String, List<WorkingActivityModel>> map = new HashMap<>();

for(WorkingActivityModel o : mList){
    if (!map.containsKey(o.getKey())) {
        List<WorkingActivityModel> list = new ArrayList<>();
        list.add(o);

        map.put(o.getKey(), list);
    } else {
        map.get(o.getKey()).add(o);
    }
}

```

In this case, I don't know how to sum corresponding sales and Shifts

**Edit**

below an example of the expected result:

[![enter image description here](https://i.stack.imgur.com/XLtad.png)](https://i.stack.imgur.com/XLtad.png)

Answer: 
You can do that using a custom merge operation defined such that performing `toMap` becomes slightly easier.

```
Collection<WorkingActivityModel> result = mList.stream()
        .collect(Collectors.toMap(WorkingActivityModel::getName, Function.identity(),
                (a, b) -> WorkingActivityModel.mergeModels(a, b))) // WorkingActivityModel::mergeModels
        .values();

```

The `mergeModels` is a static method that I have defined within `WorkingActivityModel` class such as it deals with the logic of merging two similarly named models.

```
static WorkingActivityModel mergeModels(WorkingActivityModel model1, WorkingActivityModel model2) {
    return new WorkingActivityModel(model1.name,
            Sales.mergeSales(model1.sales, model2.sales),
            Shifts.mergeShifts(model1.shifts, model2.shifts));
}

```

Of course, the `mergeSales` and `mergeShifts` follow the same pattern and are trivial to implement.
If my understanding of your question is right, this might help -

```
List<WorkingActivityModel> mList = generateList(6);

Map<String, WorkingActivityModel> map = mList.stream()
            .collect(groupingBy(WorkingActivityModel::getName))
            .entrySet().stream()
            .collect(Collectors.toMap(entry ->entry.getKey(),
                    entry -> {
                WorkingActivityModel wam = new WorkingActivityModel();
                wam.shifts = new Shifts();
                wam.shifts.shift1 = entry.getValue()
                        .stream()
                        .map(v -> v.shifts.shift1)
                        .reduce(0, Integer::sum);;
                wam.shifts.shift2 = entry.getValue()
                        .stream()
                        .map(v -> v.shifts.shift2)
                        .reduce(0, Integer::sum);
                wam.sales = new Sales();
                wam.sales.product1 = entry.getValue()
                        .stream()
                        .map(v -> v.sales.product1)
                        .reduce(0, Integer::sum);
                wam.sales.product2 = entry.getValue()
                        .stream()
                        .map(v -> v.sales.product2)
                        .reduce(0, Integer::sum);
                return wam;
            }));

```

The map will have grouped WorkingActivities by names.
The Key is the name, and value is a WorkingActiviyModel object with the sum of shifts and products.