Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing an object in stream function

How can I parse String to BigDecimal in the stream function, I would like to keep property set as a String and then parse it to BigDecimal and finally getting the sum of totals by calculating totals taken from each object. (currently on the BigDecimal::add there is a message cannot resolve method add) Thank you.

public Optional<BigDecimal> generalTotalForSingleInvoice(PDDocument pdDocument) {
    return Optional.of(new BigDecimal(findFirst(extractText(pdDocument), INVOICE_GENERAL_TOTAL)
            .replaceAll("\\.", "")
            .replaceAll(",", ".")).stripTrailingZeros());
}

public Optional<BigDecimal> sumOfGeneralTotal(List<PDDocument> document) {
    return document.stream().map(this::generalTotalForSingleInvoice).reduce(BigDecimal.ZERO, BigDecimal::add);

}
like image 859
Artjom Prozorov Avatar asked Sep 03 '26 10:09

Artjom Prozorov


2 Answers

You are creating a Stream<Optional<BigDecimal>>, and you can't reduce that Stream with a BinaryOperator<BigDecimal>, so BigDecimal::add doesn't fit.

Since your generalTotalForSingleInvoice can never return an empty Optional, it has no reason to return an Optional. You can change it to:

public BigDecimal generalTotalForSingleInvoice(PDDocument pdDocument) {
    return new BigDecimal(findFirst(extractText(pdDocument), INVOICE_GENERAL_TOTAL)
            .replaceAll("\\.", "")
            .replaceAll(",", ".")).stripTrailingZeros();
}

Now, your original Stream pipeline will work, but note that the reduce variant you are using doesn't return an Optional (since you are passing an identity value), so you should change the return type of the method:

public BigDecimal sumOfGeneralTotal(List<PDDocument> document) {
    return document.stream().map(this::generalTotalForSingleInvoice).reduce(BigDecimal.ZERO, BigDecimal::add);

}
like image 87
Eran Avatar answered Sep 05 '26 01:09

Eran


Excusing the return type based on the implementation of generalTotalForSingleInvoice, you can still use filter and map to ensure only PDDocument which are present contribute to accumulation in your reduction:

return document.stream()
        .map(this::generalTotalForSingleInvoice)
        .filter(Optional::isPresent)
        .map(Optional::get)
        .reduce(BigDecimal::add);
like image 21
Naman Avatar answered Sep 04 '26 23:09

Naman