近日老大急忙忙部置了一项任务,要求从10月1号起,从几十张账单表中,生成下面的交易统计数据
1、每个商户入网累计金额,累计笔数,最高单笔交易金额,
2、单笔超过3000元的交易次数,单笔交易金额超过3000的合计金额
3、然后2000到3000的交易金额和笔数
4、1000到2000的交易金额和笔数
5、小于1000的交易金额和笔数
可以看出2、3、4、5数据其实只是条件不一样,就是过滤出的条件不一样,数据格式是一样的。这样用jdk8新的函数式接口来实现。
现在把解决方案流程作一下回顾
1、首先是按照商户获取账单
2、根据账单进行计算
3、把计算后的结果保存到数据库
我们这边重点讲一下根据账单计算。获取的账单用List<Gt> gts表示,Gt表示账单表,有交易金额tradeMoney关键字段,
analyse是要计算后要保存到数据库的对象。
现在说一下每个统计字段怎么计算
累计金额
int tradeMoney = gts.stream().mapToInt(Gt::getTradeMoney).sum();
analyse.setMoneyTotal(CommonUtils.transferMoney(tradeMoney));
累计笔数
gts.size()
最高单笔交易金额
Optional<Gt> optional = gts.stream().max(Comparator.comparing(Gt::getTradeMoney));
optional.ifPresent(item -> analyse.setMoneyMax(CommonUtils.transferMoney(item.getTradeMoney())));
这边用到了optional对象,可以避免非空判断,读者如果不了解,请自行百度。
下面是重点了,先贴代码
// >=3000
setData(gts, (a) -> a >= 3000 * 100, analyse, GtBillMemberAnalyse::setMoney1, GtBillMemberAnalyse::setNum1);
// 2000>= and < 3000
setData(gts, (a) -> a < 3000 * 100 && a >= 2000 * 100, analyse, GtBillMemberAnalyse::setMoney2, GtBillMemberAnalyse::setNum2);
// 1000>= and <2000"
setData(gts, (a) -> a < 2000 * 100 && a >= 1000 * 100, analyse, GtBillMemberAnalyse::setMoney3, GtBillMemberAnalyse::setNum3);
// <1000
setData(gts, (a) -> a < 1000 * 100, analyse, GtBillMemberAnalyse::setMoney4, GtBillMemberAnalyse::setNum4);
可以看出来,单笔超过3000元等逻辑被抽象成Lambda表达式了,分别是
(a) -> a >= 3000 * 100, analyse
(a) -> a < 3000 * 100 && a >= 2000 * 100
等。
保存值被抽象成方法引用GtBillMemberAnalyse::setMoney1, GtBillMemberAnalyse::setNum1等,如果 不了解,请百度Java8之方法引用
下面是setData方法代码
/**
* 设置交易金额和笔数
*
* @param gts
* @param predicate 过滤函数
* @param analyse 保存的对象
* @param funcMoney 设置金额
* @param funcNum 设置笔数
*/
private void setData(List<Gt> gts, IntPredicate predicate, GtBillMemberAnalyse analyse, BiConsumer<GtBillMemberAnalyse, BigDecimal> funcMoney, BiConsumer<GtBillMemberAnalyse, Integer> funcNum) {
int totalmoney = gts.stream().mapToInt(Gt::getTradeMoney).filter(predicate).sum();
int num = (int) gts.stream().mapToInt(Gt::getTradeMoney).filter(predicate).count();
// 金额
funcMoney.accept(analyse, CommonUtils.transferMoney(totalmoney));
// 笔数
funcNum.accept(analyse, num);
}
这个变得非常简单,只有4行代码,却实现了统计计算,判断逻辑把抽象成IntPredicate,设置值被抽象成BiConsumer。
具体这些怎么使用,请百度相关文档,本篇不是入门文章