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]

    参考

  • 相关阅读:
    UVA 1386 Cellular Automaton
    ZOJ 3331 Process the Tasks
    CodeForces 650B Image Preview
    CodeForces 650A Watchmen
    CodeForces 651B Beautiful Paintings
    CodeForces 651A Joysticks
    HUST 1601 Shepherd
    HUST 1602 Substring
    HUST 1600 Lucky Numbers
    POJ 3991 Seinfeld
  • 原文地址:https://www.cnblogs.com/cdfive2018/p/15327915.html
Copyright © 2011-2022 走看看