java8新特性中lambda表达式的使用(下)

二、实战案例


1、背景


公司有个需求是根据人汇总每个月的报税信息,这个功能本来上线了,同事做的,她第一步拿到每个月的数据,遍历所有数据,放入map中,map的键是人的唯一标识,值是该人这个月的报税信息,第二步遍历每个map的值进行金额相加得到每个人的汇总信息。现在又需要细分月度汇总的维度,根据人,税目,公司进行分别汇总,这个场景使用lambda就比较简单了,先按照人分组,再按照公司分组,最后按照税目分组,拿到一个map,最后进行汇总计算。为了复现这个场景,第一步生成测试数据,第二步进行汇总


2、测试数据生成


(1)报税信息Bean

  1. tax_type 税目
  2. document_property 公司主体
  3. lectrue  人唯一编码
  4. 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基础笔记公众号,共勉。

上一篇:Asp.Net Web API 2第七课——Web API异常处理


下一篇:3.7 su命令 3.8 sudo命令 3.9 限制root远程登录