Java 新手又来请教问题了, 把 mysql join 查询 改成单表查询然后自己组装, 求问如何优化我写的 stream 操作 - V2EX
ccppgo
V2EX    Java

Java 新手又来请教问题了, 把 mysql join 查询 改成单表查询然后自己组装, 求问如何优化我写的 stream 操作

  •  
  •   ccppgo Jul 15, 2021 2491 views
    This topic created in 1762 days ago, the information mentioned may be changed or developed.

    代码如下:

    WmHBuQ.png WmHwjg.png

    public class Service{ public IPage<ChannelAgentOrgVO> getChannelAgentTeamStream(Page<ChannelAgentOrgVO> page, Channel channel) { Page<Channel> channelPage = this.getPage(new Page<>(page.getCurrent(), page.getSize()), channel); Stream<Channel> channelStream = channelPage.getRecords().stream(); Stream<ChannelAgentOrgVO> voStream = channelStream.map(c -> { ChannelAgentOrgVO vo = new ChannelAgentOrgVO(); vo.setChannel(c); return vo; }); List<Long> channelOrgIds = channelPage.getRecords().stream().map(Channel::getChannelOrgId).collect(Collectors.toList()); List<Long> agentOrgIds = channelPage.getRecords().stream().map(Channel::getAgentOrgId).collect(Collectors.toList()); List<Long> agentTeamIds = channelPage.getRecords().stream().map(Channel::getAgentTeamId).collect(Collectors.toList()); List<ChannelOrg> channelOrgList = channelOrgService.lambdaQuery().in(ChannelOrg::getId, channelOrgIds) .select(ChannelOrg::getId, ChannelOrg::getCode, ChannelOrg::getName, ChannelOrg::getFullName, ChannelOrg::getType) .list(); List<Org> agentOrgList = agentOrgService.lambdaQuery().in(Org::getId, agentOrgIds) .select(Org::getId, Org::getCode, Org::getName, Org::getFullName, Org::getType) .list(); List<AgentTeam> agentTeamList = agentTeamService.lambdaQuery().in(AgentTeam::getId, agentTeamIds) .select(AgentTeam::getId, AgentTeam::getName, AgentTeam::getFullName, AgentTeam::getAddressDetail, AgentTeam::getAddressName, AgentTeam::getAddressContact) .list(); voStream = voStream.peek(vo -> channelOrgList.forEach(channelOrg -> { if (Objects.equals(channelOrg.getId(), vo.getChannel().getChannelOrgId())) { vo.setChannelOrg(channelOrg); } })); voStream = voStream.peek(vo -> agentOrgList.forEach(agentOrg -> { if (Objects.equals(agentOrg.getId(), vo.getChannel().getAgentOrgId())) { vo.setAgentOrg(agentOrg); } })); voStream = voStream.map(vo -> { agentTeamList.forEach(agentTeam -> { if (Objects.equals(agentTeam.getId(), vo.getChannel().getAgentTeamId())) { vo.setAgentTeam(agentTeam); } }); return vo; }); return new PageResult<>(channelPage, voStream.collect(Collectors.toList())).getVoPage(); } } 
    19 replies    2021-07-17 11:31:10 +08:00
    shanghai1943
        1
    shanghai1943  
       Jul 15, 2021
    为什么不把 xxOrgList 转成 Map<Long, Object> 的形式来组装数据?
    ccppgo
        2
    ccppgo  
    OP
       Jul 15, 2021
    @shanghai1943 我很想这么做.. 但是我好像有点不开窍, 大佬能直接改我的代码让我学习下么.. 主楼已经把整个方法的代码贴出来了
    xuanbg
        3
    xuanbg  
       Jul 15, 2021
    你自己组装的过程还能怎么优化?只能在查询上面进行优化。
    itechify
        4
    itechify  
    PRO
       Jul 15, 2021
    说实话,这里的 stream 没必要,为了用 sream 而用 stream,没有解决最核心的耗时性能问题

    channel,agent,agentTeam 各个 ID 集合,只需要 for 循环一次 channelPage.getRecords()就可以得到而代码用了三次 channelPage.getRecords().stream().map(Channel::getXxxId)

    voStream 三次 peek/map 也没必要,只需要一次 for 循环一次就可以 setChannelOrg/setAgentOrg/setAgentTeam
    并且 setChannelOrg/setAgentOrg/setAgentTeam,可以先将 hannelOrgList 、agentOrgList 、agentTeamList 先转三个 map,而不是形如 cchannelOrgList.forEach 。。。if (Objects.equals(channelOrg.getId(), vo.getChannel().getChannelOrgId())。。。这种每次都遍历 list
    ccppgo
        5
    ccppgo  
    OP
       Jul 15, 2021
    @xuanbg 其实我意思是想看看各位大佬 操作 java stream 的 api 是怎么写, 有没有优化空间, 查询上面应该没问题了, 只是简单的单表查询用后用 id 关联..
    ccppgo
        6
    ccppgo  
    OP
       Jul 15, 2021
    @oneisall8955 是的, 这其实就是我的问题所在, 我想看看怎么写这种操作, 因为不是很熟悉 Java,刚写第二周
    mitsuizzz
        7
    mitsuizzz  
       Jul 15, 2021
    可以先把 id 查出来,然后并行通过 id 去查附加信息,然后循环一次,把信息组装下
    shanghai1943
        8
    shanghai1943  
       Jul 15, 2021
    Map<Long, ChannelOrg> map =channelOrgList.stream().collect(Collectors.toMap(ChannelOrg::geChannelOrgId,ChannelOrg->ChannelOrg));
    其他两个类似转化
    然后用一个 for 循环生成最终对象并且把这三个 map 根据 id 获取 value 然后 set 到最终对象里
    itechify
        9
    itechify  
    PRO
       Jul 15, 2021
    @ccppgo #6 list 转 map 很简单吧

    ```
    class Foo{
    int code;
    string name;
    }

    // list 通过 stream 转 map
    List<Foo> list = new ArrayList<>();
    Map<Integer, Foo> map = list.stream().collect(Collectors.toMap(Foo::getCode, Function.identity(), (f1, f2) -> f1));
    Foo foo = map.get(1);

    // 使用 Guava 库
    Map<Integer, Foo> map = Maps.uniqueIndex(list,Foo::getCode);
    ```
    ccppgo
        10
    ccppgo  
    OP
       Jul 15, 2021
    @shanghai1943
    @mitsuizzz
    @oneisall8955

    三位大佬, 我好像有点开悟了, 请问还有优化空间吗
    [![WnF2wt.png]( https://z3.ax1x.com/2021/07/15/WnF2wt.png)]( https://imgtu.com/i/WnF2wt)
    shanghai1943
        11
    shanghai1943  
       Jul 15, 2021
    你这 voStream 里 setXXX 是不是跟下面 for 循环里做的事情重复了?
    ccppgo
        12
    ccppgo  
    OP
       Jul 15, 2021
    #10

    还有个问题, stream 和 foreach 都能做得时候, 使用 stream 好过 foreach 吗
    ccppgo
        13
    ccppgo  
    OP
       Jul 15, 2021
    @shanghai1943 是的, 我是想知道 使用 stream 和 foreach 哪个更好
    shanghai1943
        14
    shanghai1943  
       Jul 15, 2021
    一般比较更好的时候会参考性能,可读性,以及后续维护成本来看。站在这几个方面来看的话,你觉得哪个更好?
    ccppgo
        15
    ccppgo  
    OP
       Jul 15, 2021
    @shanghai1943 我看过一些网上的分析, 貌似数据量少时,foreach 性能稍微高一丢丢, 数据量大时 stream 性能更高, 而且还可以用多核并行, 并且 stream 的可读性和维护性 比 foreach 要好, 我感觉比较喜欢 stream
    thetbw
        16
    thetbw  
       Jul 16, 2021
    lambdaQuery 是用于哪个 orm 吗
    ccppgo
        17
    ccppgo  
    OP
       Jul 16, 2021
    @thetbw mybatis plus 自带的
    running17
        18
    running17  
       Jul 17, 2021
    每次在项目里看到这种 forEach 嵌套 forEach 去筛选取值的,都会忍不住去改成 Map 的形式,一次循环可以完成事情的,虽然小数据量下效率不会有很大的提升,但是感觉思路习惯还是养成的==
    ccppgo
        19
    ccppgo  
    OP
       Jul 17, 2021
    @running17 我已经学会了哈哈哈,stream toMap 永远滴神
    About     Help     Advertise     Blog     API     FAQ     Solana     3297 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 46ms UTC 14:07 PVG 22:07 LAX 07:07 JFK 10:07
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86