【List合并处理】涉及值计算及非空判断

1、使用Stream流进行合并

 public List<IndustryResultDto> findTest(Long industryChainId, String level) {
        List<IndustryResultDto> flow = findAmountFlowByLevel( industryChainId, "流入", level,"0" );
        List<IndustryResultDto> out = findAmountFlowByLevel( industryChainId, "流出", level,"0" );
        return Stream.concat(
                        Optional.ofNullable(flow).map(List::stream).orElseGet(Stream::empty),
                        Optional.ofNullable(out).map(List::stream).orElseGet(Stream::empty)
                )
                .collect(Collectors.toMap(
                        IndustryResultDto::getIndustryId,
                        Function.identity(),
                        (existing, newValue) -> {
                            IndustryResultDto result = new IndustryResultDto();
                            result.setIndustryId(existing.getIndustryId());
                            result.setResult(Optional.ofNullable(existing.getResult()).orElse(BigDecimal.ZERO)
                                    .subtract(Optional.ofNullable(newValue.getResult()).orElse(BigDecimal.ZERO)));
                            return result;
                        }
                ))
                .values()
                .stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

相关代码解释

这个方法 findTest计算并返回一个包含 IndustryResultDto 对象的列表。列表中的每个对象代表一个行业的净流量(流入量减去流出量)。

下面详细解释每一步骤:

1、获取流入和流出数据:

List<IndustryResultDto> flow = findAmountFlowByLevel(industryChainId, "流入", level, "0");
List<IndustryResultDto> out = findAmountFlowByLevel(industryChainId, "流出", level, "0");

使用 findAmountFlowByLevel 方法分别获取指定产业链 ID 和层级的流入和流出数据。这两个列表 flow 和 out 存储了对应的 IndustryResultDto 对象。

2、合并流入和流出数据:

return Stream.concat(
    Optional.ofNullable(flow).map(List::stream).orElseGet(Stream::empty),
    Optional.ofNullable(out).map(List::stream).orElseGet(Stream::empty)
)

使用 Stream.concat 将 flow 和 out 两个流合并。如果 flow 或 out 为空,则使用 Stream::empty 创建一个空流。

3、创建 ID 到 IndustryResultDto 的映射:

.collect(Collectors.toMap(
    IndustryResultDto::getIndustryId, // key: 使用 IndustryResultDto 的 industryId
    Function.identity(), // value: 直接使用 IndustryResultDto 对象
    (existing, newValue) -> { // 如果 key 冲突时执行的合并逻辑
        IndustryResultDto result = new IndustryResultDto();
        result.setIndustryId(existing.getIndustryId());
        result.setResult(
            Optional.ofNullable(existing.getResult()).orElse(BigDecimal.ZERO)
                .subtract(Optional.ofNullable(newValue.getResult()).orElse(BigDecimal.ZERO))
        );
        return result;
    }
    
1、toMap 参数解释:

keyMapper (IndustryResultDto::getIndustryId): 使用 IndustryResultDto 的 industryId 作为键。
valueMapper (Function.identity()): 直接使用 IndustryResultDto 对象作为值。
mergeFunction: 当键冲突(即同一个 industryId 多次出现)时,使用合并函数来处理冲突。
))
2、合并函数:
(existing, newValue) -> {
    IndustryResultDto result = new IndustryResultDto();
    result.setIndustryId(existing.getIndustryId()); // 设置 industryId

    // 计算 result 的值
    result.setResult(
        Optional.ofNullable(existing.getResult()).orElse(BigDecimal.ZERO) // 取 existing 的 result,如果为 null 则用 BigDecimal.ZERO
            .subtract(Optional.ofNullable(newValue.getResult()).orElse(BigDecimal.ZERO)) // 减去 newValue 的 result,如果为 null 则用 BigDecimal.ZERO
    );
    return result; // 返回新的 IndustryResultDto 对象
}
合并逻辑的工作原理
	当 existing 和 newValue 都有相同的 industryId 时:
	创建一个新的 IndustryResultDto 对象 result。
	设置 result 的 industryId 为 existing 的 industryId。
	计算 result 的 result 值:
	取 existing 的 result 值,如果为 null 则使用 BigDecimal.ZERO。
	取 newValue 的 result 值,如果为 null 则使用 BigDecimal.ZERO。
	用 existing 的 result 值减去 newValue 的 result 值。
	返回新的 result 对象。

将合并后的流收集成一个 Map,其中 key 是 IndustryResultDto 的 industryId,value 是 IndustryResultDto 对象。若同一个 industryId 有多个值,则执行合并逻辑:

创建一个新的 IndustryResultDto 对象 result。
设置其 industryId。
计算 result 值:existing 的 result 减去 newValue 的 result。如果 result 为 null,则默认使用 BigDecimal.ZERO。

4、提取 Map 中的值并过滤非空值:

.values().stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());

这一步骤将 Map 中的所有值(IndustryResultDto 对象)转换为流,并过滤掉所有的 null 值,最后收集到一个列表中。

综上所述,整个方法 findAmountFlowSubtractByLevel 的主要目的是计算每个产业的净流量,并返回一个非空的 IndustryResultDto 列表。每个 IndustryResultDto 对象包含产业 ID 和净流量(流入减去流出)

2、使用for循环方式

public List<DistrictResultDto> techTest(Long industryChainId) {
        Map<String, Map<String,Object>> patentAndCopiesMap = baseMapper.getPatentAndCopiesByArea(industryChainId);
        Map<String, Map<String,Object>> allCompanymap = baseMapper.getAllCompanyByArea(industryChainId);
        List<DistrictResultDto> districtResultDtoList = new ArrayList<>();
        Set<String> allCompanyKeys = new HashSet<>(allCompanymap.keySet());
        for (String allCompanyKey : allCompanyKeys) {
            DistrictResultDto districtResultDto = new DistrictResultDto();
            districtResultDto.setDistrict(allCompanyKey);
            Map<String, Object> allCompany = allCompanymap.get(allCompanyKey);
            if (0L == Long.parseLong( MapUtil.getStr(allCompany, "result"))){
                districtResultDto.setResult(BigDecimal.ZERO);
            }else {
                Map<String, Object> patentAndCopies = patentAndCopiesMap.get(allCompanyKey);
                if (null == patentAndCopies ){
                    districtResultDto.setResult(BigDecimal.ZERO);
                }else {
                    Long patentAndCopiesLong = Long.parseLong(MapUtil.getStr(patentAndCopies, "result")) ;
                    Long allCompanyLong = Long.parseLong(MapUtil.getStr(allCompany, "result")) ;
                    BigDecimal result = BigDecimal.valueOf(patentAndCopiesLong/allCompanyLong);
                    districtResultDto.setResult(result);
                }
            }
            districtResultDtoList.add(districtResultDto);
        }
        return districtResultDtoList;
    }

1、获取数据:

Map<String, Map<String, Object>> patentAndCopiesMap = baseMapper.getPatentAndCopiesByArea(industryChainId);

调用 baseMapper.getPatentAndCopiesByArea 方法,根据 industryChainId 获取一个包含专利和复印件数据的 Map。这个 Map 的键是区域名,值是一个包含相关数据的 Map。

2、获取其他数据:

Map<String, Map<String, Object>> allCompanymap = baseMapper.getAllCompanyByArea(industryChainId);

调用 baseMapper.getAllCompanyByArea 方法,根据 industryChainId 获取一个包含所有公司数据的 Map。这个 Map 的键也是区域名,值是一个包含相关数据的 Map。

3、初始化结果列表和所有公司键的集合:

List<DistrictResultDto> districtResultDtoList = new ArrayList<>();
Set<String> allCompanyKeys = new HashSet<>(allCompanymap.keySet());

创建一个空的 DistrictResultDto 列表 districtResultDtoList,用于存储最终的结果。并从 allCompanymap 中获取所有区域的键,存入 allCompanyKeys 集合。

4、遍历所有公司键集合,计算每个区域的结果:

for (String allCompanyKey : allCompanyKeys) {
    DistrictResultDto districtResultDto = new DistrictResultDto();
    districtResultDto.setDistrict(allCompanyKey);
    Map<String, Object> allCompany = allCompanymap.get(allCompanyKey);
    if (0L == Long.parseLong(MapUtil.getStr(allCompany, "result"))) {
        districtResultDto.setResult(BigDecimal.ZERO);
    } else {
        Map<String, Object> patentAndCopies = patentAndCopiesMap.get(allCompanyKey);
        if (null == patentAndCopies) {
            districtResultDto.setResult(BigDecimal.ZERO);
        } else {
            Long patentAndCopiesLong = Long.parseLong(MapUtil.getStr(patentAndCopies, "result"));
            Long allCompanyLong = Long.parseLong(MapUtil.getStr(allCompany, "result"));
            BigDecimal result = BigDecimal.valueOf((double) patentAndCopiesLong / allCompanyLong);
            districtResultDto.setResult(result);
        }
    }
    districtResultDtoList.add(districtResultDto);
}

遍历 allCompanyKeys 集合,对于每个区域名 allCompanyKey:

创建一个新的 DistrictResultDto 对象,并设置其 district 字段为当前区域名。
从 allCompanymap 中获取当前区域名对应的公司数据 allCompany。
检查 allCompany 中的 result 值是否为 0。如果是,设置 districtResultDto 的 result 为 BigDecimal.ZERO。
如果 result 不为 0,从 patentAndCopiesMap 中获取当前区域名对应的专利和复印件数据 patentAndCopies。如果 patentAndCopies 为 null,同样设置 result 为 BigDecimal.ZERO。
如果 patentAndCopies 不为 null,计算 patentAndCopies 中 result 与 allCompany 中 result 的比值,并设置到 districtResultDto 的 result 字段。
将 districtResultDto 添加到 districtResultDtoList 列表中。

5、返回结果列表:

return districtResultDtoList;

返回计算后的结果列表 districtResultDtoList。

总结
该方法通过从数据库中获取指定产业链 ID 对应的不同区域的数据,计算每个区域的特定结果,并将结果封装在 DistrictResultDto 对象中,最终返回一个包含所有区域计算结果的列表

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值