hope someone can help me. I have a POJO with the following structure:
public class Invoice{
private String docNum;
private String customer;
private ArrayList<InvoiceDetails> invoiceDetails;
/* Getters and setters*/
}
And another POJO with the following
public class InvoiceDetails{
private String vatGroup;
private Double vatAmount;
private Double amount;
/* Getters and setters*/
}
Besides I have a third one with the following
public class VatType{
private String vatGroup;
private Double vatAmount;
private Double amount;
/* Getters and setters*/
}
What I'm trying to do is to reduce a List
of Invoice
to a List
of VatType
grouped by vatGroup. Like de DISTINCT
clause in SQL
.
Let's say I have the following List:
InvoiceDetails idA1 = new InvoiceDetails("S1", 100.0, 40.0);
InvoiceDetails idA2 = new InvoiceDetails("S2", 140.0, 40.0);
InvoiceDetails idA3 = new InvoiceDetails("A1", 50.0, 10.0);
ArrayList<InvoiceDetails> listA = new ArrayList<>();
listA.add(idA1);
listA.add(idA2);
listA.add(idA3);
Invoice invoiceA = new Invoice();
invoiceA.setDetailList(listA);
InvoiceDetails idB1 = new InvoiceDetails("S1", 200.0, 50.0);
InvoiceDetails idB2 = new InvoiceDetails("S2", 240.0, 50.0);
InvoiceDetails idB2 = new InvoiceDetails("A1", 100.0, 20.0);
ArrayList<InvoiceDetails> listB = new ArrayList<>();
listB.add(idB1);
listB.add(idB2);
listB.add(idB3);
Invoice invoiceB = new Invoice();
invoiceB.setDetailList(listB);
List<Invoice> invoiceList = new ArrayList<>();
invoiceList.add(invoiceA);
invoiceList.add(invoiceB);
The expected result would be a List
of VatType
with the following items:
("S1",300.0,90.0)
("S2",380.0,90.0)
("A1",150.0,30.0)
How can I get this list using a stream
in one shot. Avoiding to iterate through the Lists
?
Thanks in advance
You will first need a flatMap to create a stream of all InvoiceDetails
in all Invoice
in your list. After that you can reduce with the variant of toMap that gets a merge method. Finally values()
method of Map
will get a Collection
of VatType
:
Collection<VatType> values = invoiceList.stream()
.flatMap(invoices -> invoices.getInvoiceDetails().stream())
.collect(toMap(InvoiceDetails::getVatGroup, VatType::new, (i1, i2) -> {
i1.setAmount(i1.getAmount() + i2.getAmount());
i1.setVatAmount(i1.getVatAmount() + i2.getVatAmount());
return i1;
}))
.values();
Where this VatType
constructor is used:
VatType(InvoiceDetails invoiceDetails) {
vatGroup = invoiceDetails.getVatGroup();
vatAmount = invoiceDetails.getVatAmount();
amount = invoiceDetails.getAmount();
}
You can easily make a List
from a Collection
if you need one:
List<VatType> vatTypes = new ArrayList<>(values);