利用Stream聚合函数如何对BigDecimal求和
作者:SUDDEV
利用Stream聚合函数对BigDecimal求和
数据库查找的结果经常会有List等集合,而集合中存放法是JAVA对象,对象中存在BigDecimal的字段,如果用for或者iterator遍历来累加感觉很麻烦,stream聚合函数很好的解决了这个问题.做个笔记mark一下
POJO
package test; import java.math.BigDecimal; /** * 用户实体类 * * @author suddev * @create 2018-02-26 上午11:03 **/ public class User { private long id; private BigDecimal money; public User(long id, BigDecimal money) { this.id = id; this.money = money; } // getter&setter }
在实体类中,我们可以看到实体存在一个为BigDecimal的money属性,以计算所有查询出来的用户金钱总额为例子:
package test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; /** * 测试类 * * @author suddev * @create 2018-02-26 上午11:03 **/ public class Test { public static void main(String[] args) { // 准备数据 List<User> userList = new ArrayList<User>(); for (int i = 0; i < 100; i++) { User user = new User(i,new BigDecimal(i+"."+i)); userList.add(user); } // for version BigDecimal result1 = BigDecimal.ZERO; for (User user : userList) { result1 = result1.add(user.getMoney()); } System.out.println("result1 = "+result1); // java 8 stream version BigDecimal result2 = userList.stream() // 将user对象的mongey取出来map为Bigdecimal .map(User::getMoney) // 使用reduce聚合函数,实现累加器 .reduce(BigDecimal.ZERO,BigDecimal::add); System.out.println("result2 = "+result2); } }
map
是一个对于流对象的中间操作,通过给定的方法,它能够把流对象中的每一个元素对应到另外一个对象上,这里将user对象的money取出来map为Bigdecimalreduce
是一个终结操作,它能够通过某一个方法,对元素进行削减操作。该操作的结果会放在一个Optional变量里返回。可以利用它来实现很多聚合方法比如count,max,min等。
这里利用了reduce的第二个方法重载
Treduce(T identity, BinaryOperator accumulator);
第一个参数是我们给出的初值,第二个参数是累加器,可以自己用实现接口完成想要的操作,这里使用Bigdecimal的add方法
最后reduce会返回计算后的结果
Stream流,求和计算
Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作。通常我们需要多行代码才能完成的操作,借助于Stream流式处理可以很简单的实现。
将分别使用传统的foreach 和 stream流 进行集合的求和汇总运算,废话不多说,直接上代码
创建测试的实体类
@Data @ToString public class Sys_testClass implements Serializable { private String name;//名称 private double price;//价格 private int number;//数量 private double sum_price;//商品总价格 }
插个题外话,上面的 @Date和@ToString 注解代替了我们自动生成的getting,setting和toString方法,让类看上去更简洁明了,并且当你重新添加或删除字段的时候,不用去管getting,setting方法,大大节省了开发时间及效率,如果想用的小伙伴,直接导入 lombok依赖即可
创建 Main方法
并且往集合中添加测试数据
public static void main(String[] args) { List<Sys_testClass> listTest = new ArrayList<>(); Sys_testClass test1 = new Sys_testClass(); test1.setName("商品1"); test1.setPrice(3200.0); test1.setNumber(3); test1.setSum_price(test1.getPrice()*test1.getNumber()); listTest.add(test1); Sys_testClass test2 = new Sys_testClass(); test2.setName("商品2"); test2.setPrice(1599.0); test2.setNumber(6); test2.setSum_price(test2.getPrice()*test2.getNumber()); listTest.add(test2); Sys_testClass test3 = new Sys_testClass(); test3.setName("商品3"); test3.setPrice(999.0); test3.setNumber(2); test3.setSum_price(test3.getPrice()*test3.getNumber()); listTest.add(test3); }
利用传统foreach循环遍历
得到集合中所有价格的和,代码如下
double sum_price=0.00; //价格总和的初始值 for (Sys_testClass sys_testClass : listTest) { sum_price+=sys_testClass.getSum_price();//循环相加 集合中的总价格 } System.err.println(sum_price);// 打印输出值为: 21192.0
利用java8新特性(Stream流)遍及集合
只需要一行代码
double sum_price = listTest.stream().mapToDouble(Sys_testClass::getSum_price).sum(); System.err.println(sum_price);//打印输出值为: 21192.0
注:价格是double 类型,所以这里用了mapToDouble方法,如果是int类型求和 替换成 mapToInt方法即可
两者相比可以看出传统循环需要 4 行代码,而新特性只需要 1 行代码,速度上其实一样的,底层都是循环遍历得到结果,但是集合多了,开发时间就将会大大节省
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。