二、实战案例
1、背景
公司有个需求是根据人汇总每个月的报税信息,这个功能本来上线了,同事做的,她第一步拿到每个月的数据,遍历所有数据,放入map中,map的键是人的唯一标识,值是该人这个月的报税信息,第二步遍历每个map的值进行金额相加得到每个人的汇总信息。现在又需要细分月度汇总的维度,根据人,税目,公司进行分别汇总,这个场景使用lambda就比较简单了,先按照人分组,再按照公司分组,最后按照税目分组,拿到一个map,最后进行汇总计算。为了复现这个场景,第一步生成测试数据,第二步进行汇总
2、测试数据生成
(1)报税信息Bean
- tax_type 税目
- document_property 公司主体
- lectrue 人唯一编码
- sum_money 每条记录的金额
import java.math.BigDecimal; public class DataRecord { private Integer id; private String tax_type; private String document_property; private BigDecimal sum_money; private Integer lecture; public DataRecord(Integer id, String tax_type, String document_property, BigDecimal sum_money, Integer lecture) { this.id = id; this.tax_type = tax_type; this.document_property = document_property; this.sum_money = sum_money; this.lecture = lecture; } @Override public String toString() { return "DataRecord{" + "id=" + id + ", tax_type='" + tax_type + '\'' + ", document_property='" + document_property + '\'' + ", sum_money=" + sum_money + ", lecture=" + lecture + '}'; } }
3、生产数据Utils
import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; public class DataUtils { public static String[] taxs = new String[]{"稿酬所得", "劳务报酬所得", "特许权使用费所得"}; public static String[] documentPropertys = new String[]{"A公司", "B公司"}; public static int[] lectures = new int[]{100, 101, 102, 103}; public static List<DataRecord> getDatas() { List<DataRecord> list = new ArrayList<>(); for (int i = 0; i < 100; i++) { list.add(new DataRecord(i, taxs[i % 3], documentPropertys[i % 2], new BigDecimal(i), lectures[i % 4])); } return list; } }
4、最后我们使用lambda表达式进行汇总
(1)主要是这段代码,我streamr方法将数据写入流中,然后使用filter方法过滤掉税目,主体,人唯一编码为空的问题数据,最后使用collect()方法进行数据收集,在collect方法中,我们先按照人唯一编码使用groupingBy方法进行分组,然后将分组的数据再使用groupingBy方法按照主体分组,最后将二次分组的数据再按照税目使用groupingBy方法分组,结束以后就获取了一个分好组的大map。
//根据tax documentProperty ,lecture 分组 Map<Integer, Map<String, Map<String, List<DataRecord>>>> bigMap = list.stream().filter(it -> it.getDocument_property() != null && it.getLecture() != null && it.getTax_type() != null ).collect(Collectors.groupingBy(DataRecord::getLecture, Collectors.groupingBy(DataRecord::getDocument_property, Collectors.groupingBy(DataRecord::getTax_type))));
(2)bigMap长这样,map套map
{100={A公司={稿酬所得=[DataRecord{id=0, tax_type='稿酬所得', document_property='A公司', sum_mo
(3)获取大map后,遍历改map,拿到sum_money进行加和,加入集合中。汇总Test类如下,可复制进行运行。
package com.jiankang.javacoretechnologythetenversion.dchapter10.v2; /* *@create by jiankang *@date 2020/7/21 time 17:54 * lambda 表达式研究 */ import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; public class Test { public static void main(String[] args) { List<DataRecord> results = new ArrayList<>(); List<DataRecord> list = DataUtils.getDatas(); //根据tax documentProperty ,lecture 分组 Map<Integer, Map<String, Map<String, List<DataRecord>>>> bigMap = list.stream().filter(it -> it.getDocument_property() != null && it.getLecture() != null && it.getTax_type() != null ).collect(Collectors.groupingBy(DataRecord::getLecture, Collectors.groupingBy(DataRecord::getDocument_property, Collectors.groupingBy(DataRecord::getTax_type)))); Set<Integer> lectures = bigMap.keySet(); for (Integer lecture : lectures) { Map<String, Map<String, List<DataRecord>>> document_propertyMap = bigMap.get(lecture); Set<String> document_propertys = document_propertyMap.keySet(); for (String document_property : document_propertys) { Map<String, List<DataRecord>> tax_typeMap = document_propertyMap.get(document_property); Set<String> tax_types = tax_typeMap.keySet(); for (String tax_type : tax_types) { List<DataRecord> dataRecords = tax_typeMap.get(tax_type); if (dataRecords != null && dataRecords.size() > 0) { DataRecord result = new DataRecord(null, null, null, new BigDecimal(0), null); for (DataRecord dataRecord : dataRecords) { result.setSum_money(result.getSum_money().add(dataRecord.getSum_money())); } result.setDocument_property(document_property); result.setLecture(lecture); result.setTax_type(tax_type); results.add(result); } } } } results.forEach(it -> System.out.println(it.toString())); System.out.println(results.size()); } }
(4)最后汇总后结果如下:
DataRecord{id=null, tax_type='稿酬所得', document_property='A公司', sum_money=432, lecture=100} DataRecord{id=null, tax_type='特许权使用费所得', document_property='A公司', sum_money=400, lecture=100} DataRecord{id=null, tax_type='劳务报酬所得', document_property='A公司', sum_money=368, lecture=100} DataRecord{id=null, tax_type='稿酬所得', document_property='B公司', sum_money=408, lecture=101} DataRecord{id=null, tax_type='特许权使用费所得', document_property='B公司', sum_money=376, lecture=101} DataRecord{id=null, tax_type='劳务报酬所得', document_property='B公司', sum_money=441, lecture=101} DataRecord{id=null, tax_type='稿酬所得', document_property='A公司', sum_money=384, lecture=102} DataRecord{id=null, tax_type='特许权使用费所得', document_property='A公司', sum_money=450, lecture=102} DataRecord{id=null, tax_type='劳务报酬所得', document_property='A公司', sum_money=416, lecture=102} DataRecord{id=null, tax_type='稿酬所得', document_property='B公司', sum_money=459, lecture=103} DataRecord{id=null, tax_type='特许权使用费所得', document_property='B公司', sum_money=424, lecture=103} DataRecord{id=null, tax_type='劳务报酬所得', document_property='B公司', sum_money=392, lecture=103}
三、总结
以上就是对lambda表达式的一些见解和经验,最后的业务场景实战算是比较复杂了,但是lambda表达对解决实际问题确实十分方便,逻辑更加清晰,希望可以帮到你,欢迎关注java基础笔记公众号,共勉。