I have a object list, which I need to group by 2 different atributes and then sum the values of an attribute, the structure of my object is something like this:
private Long id1;
private Long id2;
private Double amountReserved;
private Double amountRequired;
//... more atributes and getters and setters
So, I then have a list, for example:
List<MyList> list = Arrays.asList(
list(1, A, 50, 200)
list(1, A, 50, 200)
list(1, B, 0, 100)
list(2, A, 10, 15)
list(2, A, 5, 15)
list(3, A, 0, 25));
What I am trying to achieve is a new list with the below structure:
list(1, A, 100, 100)
list(1, B, 0, 100)
list(2, A, 15, 0)
list(3, A, 0, 25)
Elucidating what is the requisite I am trying to achieve:
- Group objects by id1 and id2
- sum the
amountReserved
of the grouped object - subtract
amountRequired
from the summedamountReserved
What I have so far:
This one got me the groupings as I wanted
Map<Long, Map<String, List<MyList>>> map = null;
map = lista.stream().collect(Collectors.groupingBy(PreSeparacaoDto::getCodigoPedido,
Collectors.groupingBy(PreSeparacaoDto::getCodigoProduto)));
This one sums by group id1, but I am struggling to add the second groupingby on it, as I get syntax errors:
lista.stream()
.collect(Collectors.groupingBy(PreSeparacaoDto::getCodigoPedido,
Collectors.summingDouble(PreSeparacaoDto::getProdutoQuantidadeSeparada)))
.forEach((codigoPedido, ProdutoQuantidadeSeparada) -> System.out.println( codigoPedido + ": " + ProdutoQuantidadeSeparada ));
My problem is that I failed to get those together ( as per requisite 2) and was not even close to achieve my requisite 3.
I tried to use reduction, as explained here , but honestly, I was not able to replicate it with a single grouping, the reducing is returning an error informing that my parameters don't meet the reducing
parameters. I looked for some other options here on stackoverflow and other websites, but without success.
Can someone help me out and poiting where I am failing to combine the reduction with my group, or if that is the correct path I should be following.
You might just be looking for simply Collectors.toMap
as :
List<MyList> output = new ArrayList<>(lista.stream()
.collect(Collectors.toMap(a -> a.getId1() + "-" + a.getId2(), a -> a, (myList1, myList2) -> {
myList1.amountReserved = myList1.amountReserved + myList2.amountReserved;
myList1.amountRequired = myList1.amountRequired - myList1.amountReserved;
return myList1;
})).values());