[英]Improve Map/Reduce lambda expression by using a different BigDecimal attribute each time
I have a list of objects and each element of that list is an object that contains several BigDecimal parameters.我有一个对象列表,该列表的每个元素都是一个包含多个 BigDecimal 参数的 object。 I'm generating a new Amount object based on some calculations made on the list.我正在根据列表中的一些计算生成一个新的 Amount object。 It works fine but looks kind of repetitive.它工作正常,但看起来有点重复。
new Amount()
.withAmountIncVat(invoiceLines.stream().map(line -> line.getAmount().getAmountIncVat()).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP))
.withAmount(invoiceLines.stream().map(line -> line.getAmount().getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP))
.withVatAmount(invoiceLines.stream().map(line -> line.getAmount().getVatAmount()).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP))
Is there a better way to deal with the lambda expression in order to replace the "repeated" code?是否有更好的方法来处理 lambda 表达式以替换“重复”代码? You know, improve this function:你知道,改进这个 function:
invoiceLines.stream().map(line -> line.getAmount().XXX).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP)
In which XXX should be a different BigDecimal attribute from the object each time, and i can use this function for each assignment:其中 XXX 每次都应该是与 object 不同的 BigDecimal 属性,我可以将这个 function 用于每个分配:
new Amount()
.withVatAmount(function.apply(invoiceLines,<PERHAPS AN ADDITIONAL PARAM>))
.withAmountIncVat(function.apply(invoiceLines,<PERHAPS AN ADDITIONAL PARAM>))
.withAmount(function.apply(invoiceLines,<PERHAPS AN ADDITIONAL PARAM>))
Since operations, you perform in these stream-pipelines differs only with a function extracting BigDecimal
value, to avoid redundancy you can introduce a method expecting a source List
and a function as its arguments.由于操作,您在这些流管道中执行的操作仅与提取BigDecimal
值的 function 不同,为避免冗余,您可以引入一种期望源List
和function作为其 ZDBC11CAA5BDA8882E4
Note that keeping your functions small and well-readable makes the code more maintainable.请注意,使您的函数保持小而易读使代码更易于维护。 And it's also better to have a code that consumes a function and uses it internally than invoking Function.apply()
manually.与手动调用Function.apply()
相比,使用 function并在内部使用它的代码也更好。
That's how the method containing your stream logic might be implemented:这就是包含您的 stream 逻辑的方法可以如何实现的方式:
public static <T> BigDecimal reduce(List<T> list,
Function<T, BigDecimal> mapper) {
return list.stream()
.map(mapper)
.reduce(BigDecimal.ZERO, BigDecimal::add)
.setScale(2, RoundingMode.HALF_UP);
}
The code responsible for instantiation and infantilization of the Amount
would look like that:负责Amount
的实例化和幼稚化的代码如下所示:
new Amount()
.withAmountIncVat(reduce(invoiceLines, line -> line.getAmount().getAmountIncVat()))
.withAmount(reduce(invoiceLines, line -> line.getAmount().getAmount()))
.withVatAmount(reduce(invoiceLines, line -> line.getAmount());
Alexander Ivanchenko's answer can be made a bit simpler by making it less generic.亚历山大·伊万琴科的答案可以通过使其不那么通用而变得更简单一些。 Assuming that line
is an instance of Line
and its getAmount()
method returns an Amount
(replace these as necessary):假设line
是Line
的一个实例,并且它的getAmount()
方法返回一个Amount
(根据需要替换它们):
private static BigDecimal reduce(List<Line> lines, Function<Amount, BigDecimal> mapper) {
return lines.stream()
.map(Line::getAmount)
.map(mapper)
.reduce(BigDecimal.ZERO, BigDecimal::add)
.setScale(2, RoundingMode.HALF_UP);
}
new Amount()
.withAmountIncVat(reduce(invoiceLines, Amount::getAmountIncVat))
.withAmount(reduce(invoiceLines, Amount::.getAmount))
.withVatAmount(reduce(invoiceLines, Amount::getVatAmount);
I just tried out to create such a reusable function and I think I found a way to do it.我刚刚尝试创建这样一个可重复使用的 function,我想我找到了一种方法。 I used the BiFunction
interface that defines a function with two inputs.我使用了BiFunction
接口,它定义了一个带有两个输入的 function。 In your case it would be the list as well as a function to extract the needed BigDecimal
from the Amount
object.在您的情况下,它将是列表以及 function 从Amount
object 中提取所需的BigDecimal
。
The result should be the same as with your original code:结果应该与您的原始代码相同:
BiFunction<List<Line>, Function<Line, BigDecimal>, BigDecimal> function =
(list, extractor) -> list.stream().map(extractor)
.reduce(BigDecimal.ZERO, BigDecimal::add)
.setScale(2, RoundingMode.HALF_UP);
new Amount().withVatAmount(function
.apply(invoiceLines, line -> line.getAmount().getVatAmount()));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.