嵌套POJO的流列表到另一个POJO列表

时间:2017-06-20 11:42:22

标签: java list java-8 java-stream pojo

希望有人可以帮助我。我有一个POJO,结构如下:

public class Invoice{

private String docNum;
private String customer;
private ArrayList<InvoiceDetails> invoiceDetails;

/* Getters and setters*/
}

还有另外一个POJO

public class InvoiceDetails{

private String vatGroup;
private Double vatAmount;
private Double amount;

/* Getters and setters*/
}

此外,我还有第三个

public class VatType{

private String vatGroup;
private Double vatAmount;
private Double amount;

/* Getters and setters*/
}

我尝试做的是将List Invoice减少到由{vatGroup}分组的List VatType。与DISTINCT中的de SQL子句一样。 让我们说我有以下列表:

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);

预期结果为List VatType,其中包含以下内容:

("S1",300.0,90.0)
("S2",380.0,90.0)
("A1",150.0,30.0)

如何一次性使用stream获取此列表。避免迭代Lists? 提前致谢

4 个答案:

答案 0 :(得分:2)

首先,您需要flatMap在列表中的所有InvoiceDetails中创建所有Invoice的信息流。之后,您可以使用获得合并方法的toMap变体进行缩减。最后values() Map Collection方法将获得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();

VatType

使用此VatType(InvoiceDetails invoiceDetails) { vatGroup = invoiceDetails.getVatGroup(); vatAmount = invoiceDetails.getVatAmount(); amount = invoiceDetails.getAmount(); } 构造函数的地方:

List

如果您需要,可以轻松地从Collection制作List<VatType> vatTypes = new ArrayList<>(values);

NetworkInterface.GetAllNetworkInterfaces();

答案 1 :(得分:1)

您可以使用Java stream Function:

Function<InvoiceDetails, VatType> myF = t -> new VatType(t.getVatGroup(), t.getVatAmount(), t.getAmount());

然后流而不是使用:

List<VatType> myLocations = 
        invoiceList.stream()
        .map(Invoice::getInvoiceDetails)
        .flatMap(Collection::stream)
        .map(myF)
        .collect(Collectors.<VatType>toList());

答案 2 :(得分:1)

以下是使用Java 8的ListMap新功能的方法,没有流:

Map<String, VatType> map = new HashMap<>();

invoiceList.forEach(i -> i.getDetailList().forEach(d ->
    map.merge(
        d.getVatGroup(),
        new VatType(d.getVatGroup(), d.getVatAmount(), d.getAmount()),
        (left, right) -> {
            left.setAmount(left.getAmount() + right.getAmount());
            left.setVatAmount(left.getVatAmount() + right.getVatAmount());
            return left;
        })));

List<VatType> result = new ArrayList<>(map.values());

如果您可以向VatType添加一个构造函数,该构造函数接受一个InvoiceDetail实例和一个结合了两个merge实例的VatType方法:

public VatType(String vatGroup, Double vatAmount, Double amount) {
    this.vatGroup = vatGroup;
    this.vatAmount = vatAmount;
    this.amount = amount;
}

public VatType(InvoiceDetails details) {
    this(details.getVatGroup(), details.getVatAmount(), details.getAmount());
}

public VatType merge(VatType another) {
    this.vatAmount += another.vatAmount;
    this.amount += another.amount;
    return this;
}

然后,您可以将第一个片段简化为:

Map<String, VatType> map = new HashMap<>();

invoiceList.forEach(i -> i.getDetailList().forEach(d ->
        map.merge(d.getVatGroup(), new VatType(d), VatType::merge)));

List<VatType> result = new ArrayList<>(map.values());

答案 3 :(得分:0)

如果这是项目中的常见任务,您还可以使用dozer library