码迷,mamicode.com
首页 > 其他好文 > 详细

解决循环调用的两种方式

时间:2020-03-17 19:41:07      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:请求   规格   put   直接   foreach   object   代码示例   map   名称   

需求描述

在日常开发中,我们都应该去避免循环调用。以循环dubbo调用为例,dubbo调用需要走局域网络发送数据,唤起目标服务的dubbo线程,占用数据库连接,最后接收数据这一漫长的过程。如果循环多次调用,会有巨大的性能开销。如:调用主数据请求100条商品信息优化成批量后,性能将会有90%以上的提升。而平时解决循环调用最常用的方法就是将循环调用改为批量操作(批量新增、批量修改、批量查询),批量新增和批量修改都比较好解决,思路就是先定义一个对象List,然后将需要新增、修改的对象存入这个List,然后在业务逻辑处理完的最后再来进行批量新增、修改。

这里我主要记录的是解决循环查询的思路,因为在改为批量查询过后还需要做一步数据转换,由List转为Map,然后再根据需求使用对应的key去这个Map中取到对应的数据即可解决循环调用,但是根据需求的不同这个List转Map会有不同的实现方式(目前我只用过两种),一种是List转为Map<String, Object>;另一种是List转为Map<String, List>。

情形一

  • List转为Map<String, Object>

    例子:现在有一个商品code列表,根据这个商品code列表去查询出来了一个商品明细列表,然后现在我需要去把这个商品明细列表转为一个key为商品code,value为商品明细的Map。这里是一个key对应一条唯一的数据。转换代码示例如下:

    // 获取商品code列表
    List<String> goodsCodeList = dtoPage.getContent().stream().map(SpecialPriceGoodsOutput::getGoodsCode)
                    .distinct().collect(Collectors.toList());
    if (!CollectionUtils.isEmpty(goodsCodeList)) {
        // 调用主数据接口获取商品名称、规格、单位
        List<BasGoodsDTO> basGoodsByCodeList = basGoodsService.getBasGoodsByCodeList(goodsCodeList);
        HashMap<String, BasGoodsDTO> goodsInfoMap = basGoodsByCodeList.stream()
                .collect(HashMap::new, (m, v) -> m.put(v.getCode(), v), HashMap::putAll);
        dtoPage.getContent().forEach(o -> {
            String goodsCode = o.getGoodsCode();
            o.setGoodsName(goodsInfoMap.get(goodsCode).getName())
                .setGoodsSpec(goodsInfoMap.get(goodsCode).getGoodsSpec())
                .setGoodsUnitName(goodsInfoMap.get(goodsCode).getBasUnitName());
        });
    }

    代码说明:dtoPage对象是一个Page<>类型的对象,包含了一些分页信息,所以需要调用getContent方法来获取DTO列表,而这个DTO列表里的对象里只有商品code有值(表里只存了code),商品名称、单位、规格等信息需要通过查询得到,然后赋值。所以第一行代码先取到商品code列表,然后调用接口批量查询商品明细,获取到商品明细列表过后就将这个商品明细列表转为一个key为商品code,value为商品明细对象的Map,然后在循环赋值商品名称、单位和规格等数据的时候直接根据商品code去这个Map中取对象、取值进行赋值。

    情形二