• 一个商品可以参与多个类型的促销活动,如满减、满赠、买赠、优惠券等活动;
  • 相同类型的活动也可能有多个;
  • 每个活动根据类型和具体的业务字段有一个活动标签,如满减活动,消费满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值更大
  • 优惠券活动没有参与,因此没有该活动的促销标签
  • 将促销活动列表按促销活动类型分组生成一个map,其中key为促销活动类型,value为活动模型vo
  • 将促销活动类型转为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]

  • java stream 处理分组后取每组最大 https://blog.csdn.net/weixin_30785593/article/details/96319304
  • Java8 stream 之groupingBy() 分组排序 https://blog.csdn.net/wysnxzm/article/details/78930110
  •