使用java 8 Stream.reduce()方法简化BigDecimal对象的求和。
从本质上讲,BigDecimals
是不可变的,这意味着一旦创建了对象,就无法对其进行修改,因此在执行算术运算时,它们并不是那么友好或高效。有许多处理原语的库,例如 Guava's math utilities,但在本教程中,我们将展示 java 8 如何简化从集合中对一系列 BigDecimal进行求和。
从 Maven 原型创建一个项目并将其导入 Eclipse,我们将更新 junit。初始化一个 BigDecimals
类型的 Arraylist,我们将在 setUp 方法中添加总和为 15 的元素。
List<BigDecimal> bigDecimalsValues = new ArrayList<>();
@Before
public void setUp () {
bigDecimalsValues.add(new BigDecimal(1));
bigDecimalsValues.add(new BigDecimal(2));
bigDecimalsValues.add(new BigDecimal(3));
bigDecimalsValues.add(new BigDecimal(4));
bigDecimalsValues.add(new BigDecimal(5));
}
让我们回顾一下在 java 8 (5, 6, 7) 之前的 java 版本中这是什么样子的。您将需要创建一个对象来存储总和值并使用 for 循环遍历 ArrayList。当您调用 .add
时,它会生成一个新对象,我们需要在其中设置 addBigDecimals
等于结果。使用 junit 断言语句,我们将验证结果是否等于 15。
@Test
public void add_big_decimals_java() {
BigDecimal addBigDecimals = new BigDecimal(0);
for (BigDecimal value : bigDecimalsValues) {
addBigDecimals = addBigDecimals
.add(new BigDecimal(value.intValue()));
}
assertEquals(new BigDecimal(15), addBigDecimals);
}
Java 8 引入了终端操作,例如平均、求和、最小、最大和计数,它们以自己的方式包装通用 Stream.reduce
。将 arraylist 转换为流将使我们能够调用传入 BigDecimal.ZERO
作为标识的通用 reduce 方法和 BigDecimal::add
累加器方法。
@Test
public void add_big_decimals_java8() {
BigDecimal sumOfBigDecimals = bigDecimalsValues.stream().reduce(
BigDecimal.ZERO, BigDecimal::add);
assertEquals(new BigDecimal(15), sumOfBigDecimals);
}
接下来,如果您正在处理 BigDecimal 列表中的空值,当您尝试将它们全部加在一起时,您很可能会遇到 NullPointerException
。使用流,我们可以在归约操作之前过滤空值以避免错误。如果您还没有使用 java 8,您可以使用 guava 并从您的数组列表中过滤空引用。
@Test
public void add_big_decimals_java8_null() {
bigDecimalsValues.add(null);
BigDecimal sumOfBigDecimals = bigDecimalsValues.stream()
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
assertEquals(new BigDecimal(15), sumOfBigDecimals);
}
在我们的最后一个片段中,我们将对 BigDecimal 类型的给定对象的字段求和。首先,我们将创建一个对象 Car
,该对象具有类型为 BigDecimal
的字段英里。将里程声明为 BigDecimal
是出于演示目的,因为您可能不会在现实世界中这样做。接下来,我们将使用菱形运算符添加 Car
对象来初始化一个列表。需要注意的是,我们添加了一个空Car对象,并使用空英里值初始化了一个Car对象。
一旦我们向Car对象添加值,我们将需要编写代码来使用 java 8 语法对列表中的所有值求和。请记住,我们首先需要过滤 null Car
和里程设置为 null 的Car对象。接下来调用 .map
并返回 BigDecimals
的流,就像以前一样,将减少值并对元素求和。
class Car {
private BigDecimal miles;
public Car(BigDecimal miles) {
super();
this.miles = miles;
}
public BigDecimal getMiles() {
return miles;
}
public void setMiles(BigDecimal miles) {
this.miles = miles;
}
}
@Test
public void add_big_decimals_java8_object() {
List<Car> vehicles = new ArrayList<>();
vehicles.add(null);
vehicles.add(new Car(null));
vehicles.add(new Car(new BigDecimal("10")));
vehicles.add(new Car(new BigDecimal("20")));
BigDecimal sumOfBigDecimals = vehicles.stream()
.filter(Objects::nonNull)
.filter(c -> c.getMiles() != null)
.map(Car::getMiles)
.reduce(BigDecimal.ZERO, BigDecimal::add);
assertEquals(new BigDecimal(30), sumOfBigDecimals);
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : http://www.leveluplunch.com/java/tutorials/036-sum-arraylist-bigdecimals-java8/
内容来源于网络,如有侵权,请联系作者删除!