登录
注册
写文章
发现
工具
百万账单秒级对账
_3t3lfz KEKfID
编辑文章
百万账单秒级对账
asfx站长
2022.08.16 10:42:23
阅读
532
####最近在做金融账单对账功能,把对账基础方法做了抽象,优化了下,由原先1w条数据对账耗时400ms提高到了100w条数据耗时800ms左右。(推荐一次50w-80w条数据进行对账,耗时80ms左右) 首先定义账单接口,两边的账单需要继承该账单接口: ``` /** * @Description: 账单接口 * @Author: whm * @CreateTime: 2022-08-11 15:50 * @Version: 1.0 */ public interface Bill { /** 订单编号 */ String getOrderNo(); /** 本账单金额,分 */ Long getAmount(); /** 获取对方账单金额 */ Long getOppositeAmount(); /** 设置对方账单金额,分;金额差错时设置 */ void setOppositeAmount(Long amount); } ``` 定义账单对账结果对象类: ``` /** * @Description: 账单对账结果 * @Author: whm * @CreateTime: 2022-08-11 15:53 * @Version: 1.0 */ @Getter @Setter public class BillReconResult<A extends Bill, B extends Bill> extends ToString { /** 对平A集合 */ private List<A> equalList = new ArrayList<>(); /** 单边A集合 */ private List<A> aSideList = new ArrayList<>(); /** 单边B集合 */ private List<B> bSideList = new ArrayList<>(); /** 金额差错A集合 */ private List<A> amountErrorList = new ArrayList<>(); /** 是否对平 */ public boolean isEqual(){ return aSideList.isEmpty() && bSideList.isEmpty() && amountErrorList.isEmpty(); } } ``` 再抽象出基础对账方法: ``` import lombok.Getter; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.BiFunction; import java.util.stream.Collectors; /** * @Description: 账单对账方法 * @Author: whm * @CreateTime: 2022-08-11 15:49 * @Version: 1.0 */ @Getter public class BillReconFunction<A extends Bill, B extends Bill> { /** * 基于订单号的对账,对比金额是否一致 * * 返回对账结果,包含:对平集合、单边A集合、单边B集合、金额差错集合 * * 注意:当前方法适合两边账单数均在100w左右(耗时:800ms) */ BiFunction<List<A>, List<B>, BillReconResult> reconFunction = (listA, listB) -> { BillReconResult<A, B> result = new BillReconResult(); if(CommonUtil.isNullOrEmpty(listA) && CommonUtil.isNullOrEmpty(listB)){ return result; }else if(CommonUtil.isNullOrEmpty(listA)){ result.setBSideList(listB); return result; }else if(CommonUtil.isNullOrEmpty(listB)){ result.setASideList(listA); return result; } // 将B集合转成以orderNo为key,B为value的Map Map<String, B> bMap = listB.stream().collect(Collectors.toMap(item -> item.getOrderNo(), v -> v)); // 遍历A集合进行对账 for(A item : listA){ B b = bMap.get(item.getOrderNo()); if(b == null){ // A单边 result.getASideList().add(item); }else{ if(b.getAmount().equals(item.getAmount())){ // 对平 result.getEqualList().add(item); }else{ // 金额差错 item.setOppositeAmount(b.getAmount()); result.getAmountErrorList().add(item); } bMap.remove(item.getOrderNo()); // 剩余的即为B单边 } } // B单边集合 result.setBSideList(new ArrayList<>(bMap.values())); return result; }; } ``` ####测试: 账单A对象: ``` /** * @Description: 账单A * @Author: whm * @CreateTime: 2022-08-11 16:55 * @Version: 1.0 */ @Data public class AA extends ToString implements Bill { private Long id; private String tradeNo; private Long tradeAmount; private Long otherTradeAmount; private String remark; public AA(Long id, String tradeNo, Long tradeAmount) { this.id = id; this.tradeNo = tradeNo; this.tradeAmount = tradeAmount; } public AA(Long id, String tradeNo, Long tradeAmount, String remark) { this.id = id; this.tradeNo = tradeNo; this.tradeAmount = tradeAmount; this.remark = remark; } @Override public String getOrderNo() { return tradeNo; } @Override public Long getAmount() { return tradeAmount; } @Override public Long getOppositeAmount() { return otherTradeAmount; } @Override public void setOppositeAmount(Long amount) { otherTradeAmount = amount; } } ``` 账单B对象: ``` @Data public class BB extends ToString implements Bill { private Long id; private String tradeNo; private Long tradeAmount; private Long otherAmount; public BB(Long id, String tradeNo, Long tradeAmount) { this.id = id; this.tradeNo = tradeNo; this.tradeAmount = tradeAmount; } @Override public String getOrderNo() { return tradeNo; } @Override public Long getAmount() { return tradeAmount; } @Override public Long getOppositeAmount() { return otherAmount; } @Override public void setOppositeAmount(Long amount) { otherAmount = amount; } } ``` 测试类: ``` /** * @Description: TODO * @Author: whm * @CreateTime: 2022-08-11 16:57 * @Version: 1.0 */ public class Test { public static void main(String[] args) { List<AA> as = new ArrayList<>(); List<BB> bs = new ArrayList<>(); for(int i = 0; i < 1000000; i++){ String s = i + ""; long l = Long.parseLong(s); as.add(new AA(l, s, l)); } for(int i = 0; i < 999900; i++){ String s = i + ""; long l = Long.parseLong(s); bs.add(new BB(l, s, l)); } long start = System.currentTimeMillis(); BillReconFunction<AA, BB> billRecon = new BillReconFunction<>(); BiFunction<List<AA>, List<BB>, BillReconResult> reconFunction = billRecon.getReconFunction(); BillReconResult result = reconFunction.apply(as, bs); // System.out.println(JSON.toJSONString(result)); System.out.println(result.getASideList().size()); System.out.println("耗时:" + (System.currentTimeMillis() - start) + "ms"); } } ``` 打印结果: ``` 100 耗时:817ms ```
我的主页
退出