場景
項目中有這樣的場景:
- 一個商品可以參與多個類型的促銷活動,如滿減、滿贈、買贈、優惠券等活動;
- 相同類型的活動也可能有多個;
- 每個活動根據類型和具體的業務字段有一個活動標簽,如滿減活動,消費滿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