zoukankan      html  css  js  c++  java
  • Java8 stream分组按某字段取最大值

    场景

    项目中有这样的场景:

    • 一个商品可以参与多个类型的促销活动,如满减、满赠、买赠、优惠券等活动;
    • 相同类型的活动也可能有多个;
    • 每个活动根据类型和具体的业务字段有一个活动标签,如满减活动,消费满200元减20元,活动标签为满200减20
    • 商品列表的界面上需要展示每个商品的促销活动标签,相同类型活动有多个只展示最新一个创建的活动标签
    • 假定活动id是递增的,新创建的活动id值更大

    促销活动类型定义:

    @Getter
    @AllArgsConstructor
    private static enum PromotionType {
        FULL_MINUS("FULL_MINUS", "满减"),
        FULL_GIFT("FULL_GIFT","满赠"),
        BUY_GIFT("BUY_GIFT","买赠"),
        COUPON("COUPON","优惠券");
    
        private String name;
        private String description;
    }
    

    促销活动模型vo定义:

    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    private static class PromotionActivityVo implements Serializable {
    
        // 活动id
        private Integer id;
    
        // 活动类型
        private PromotionType type;
    
        // 活动标签
        private String label;
    }
    

    测试用例:

    // 假定某商品参与了如下5个促销活动
    PromotionActivityVo activity1 = new PromotionActivityVo(1, PromotionType.FULL_MINUS, "满200减20");
    PromotionActivityVo activity2 = new PromotionActivityVo(2, PromotionType.FULL_MINUS, "满300减30");
    PromotionActivityVo activity3 = new PromotionActivityVo(3, PromotionType.BUY_GIFT, "买180赠10");
    PromotionActivityVo activity4 = new PromotionActivityVo(4, PromotionType.FULL_GIFT, "满150赠5");
    PromotionActivityVo activity5 = new PromotionActivityVo(5, PromotionType.FULL_GIFT, "满300赠25");
    List<PromotionActivityVo> activities = Lists.newArrayList(activity1, activity2, activity3, activity4, activity5);
    

    预期输出结果为:
    满300减30, 满300赠25, 买180赠10

    注:

    • 按促销活动类型里定义的顺序输出
    • 输出第2个满减活动和第5个满赠活动因为同类型的活动它们的id值更大
    • 优惠券活动没有参与,因此没有该活动的促销标签

    思路

    1. 将促销活动列表按促销活动类型分组生成一个map,其中key为促销活动类型,value为活动模型vo
    2. 将促销活动类型转为stream然后根据map取值,过滤掉空值,转换为label的列表

    实现

    Map<PromotionType, PromotionActivityVo> promotionTypeMap = activities.stream().collect(Collectors.groupingBy(PromotionActivityVo::getType
                    , Collectors.collectingAndThen(Collectors.reducing((o1, o2) ->
                            Long.valueOf(o1.getId()).compareTo(Long.valueOf(o2.getId())) > 0 ? o1 : o2), Optional::get)));
    List<String> labels = Arrays.stream(PromotionType.values()).map(promotionTypeMap::get).filter(Objects::nonNull).map(PromotionActivityVo::getLabel).collect(Collectors.toList());
    System.out.println(labels);
    

    其中第1步转换map可用另一种方式:

    Map<PromotionType, PromotionActivityVo> promotionTypeMap = activities.stream().collect(Collectors.toMap(PromotionActivityVo::getType, Function.identity(), (o1, o2) -> Long.valueOf(o1.getId()).compareTo(Long.valueOf(o2.getId())) > 0 ? o1 : o2));
    

    输出结果为:[满300减30, 满300赠25, 买180赠10]

    参考

  • 相关阅读:
    《Windows游戏编程技巧大师》就DirectDraw而创建DirectDraw知识笔记
    中国省城市列表(中国的性格+拼音)
    Android NDK的C++11标准支持
    DFGUI-- 标签交换 Tabstrip
    Ubuntu更改hosts档
    如何完成Nexus 9上电后激活过程
    Exception dispatching input event. use XlistView
    音乐TV2015校园招聘A第二大发行量(对中国科学院大学站)
    github basic usage in windows
    HDU 1501 Zipper(DP,DFS)
  • 原文地址:https://www.cnblogs.com/cdfive2018/p/15327915.html
Copyright © 2011-2022 走看看