整点发放优惠券怎么做?必须用到这个谷歌Map神器

64 阅读2分钟

“ 上个月的双十一,这月的双十二,打折不断,优惠不停。电商系统中发放优惠券,是一个比较常见的功能。
今天讲一个优惠券开发实战。

🍋需求

现在有一个需求,实现不同时间段发放不同优惠券,比如11.11日凌晨0-12点之间发放7折优惠券,12-18点之间发放8折优惠券,18-24点之间发放9折优惠券。

作为开发老油条🥖,你会选用什么数据结构发放优惠券呢?

🍊功能分析

首选明确,这个需求里面有个区间概念,整理如下:

开始时间(含)结束时间(不含)优惠券
0127折
12188折
18249折

数学表达: [0, 12) ==> 7折
[12, 18) ==> 8折
[18, 12) ==> 9折

🥝数据结构选择

使用TreeMap


/**  
 * the RangeTest 
 * @author Java实用技术手册  
 * @date 2022-12-17  
 */
public class RangeTest {  
  
    private static Map<Integer, String> discountMap = new TreeMap<>();  

 public static void main(String[] args) {  
     initDiscountMap();  
     System.out.println("getDiscount_11=" + getDiscount(11));  
     System.out.println("getDiscount_12=" + getDiscount(12));  
 }  
   
 public static void initDiscountMap() {  
     discountMap.put(0, Discount.DISCOUNT_7);  
     discountMap.put(12, Discount.DISCOUNT_8);  
     discountMap.put(18, Discount.DISCOUNT_9);  
 }  
   
 public static Discount getDiscount(Integer time) {  
     Objects.requireNonNull(time);  
     if (time >= 0 && time < 12) {  
         return discountMap.get(0);  
     } else if (time >= 12 && time < 18) {  
         return discountMap.get(12);  
     } else if (time >= 18 && time < 24) {  
         return discountMap.get(18);  
     }  
     return null;  
 }
}

大致思路就是使用TreeMap分段设置,查找的时候,比较当前时间处于哪个区间,然后返回对应的value。

上面的代码包括initDiscountMapgetDiscount方法,可以看出如果要新增一个时间区间的优惠券,需同时修改这2个方法,违反了代码开闭原则。

使用TreeRangeMap

之前我们说谷歌神器Guava工具类的时候,提到过多种骚气的Map,其中TreeRangeMap就是一个为区间Map。

当前POM依赖

<dependency>  
   <groupId>com.google.guava</groupId>  
   <artifactId>guava</artifactId>  
   <version>31.1-jre</version>  
</dependency>

TreeRangeMap描述的是“不相交且非空的区间”到特定值的映射。

内部存储完美符合上面的数学表达式。 [0, 12) ==> 7折
[12, 18) ==> 8折
[18, 12) ==> 9折

使用方法: 先使用TreeRangeMap.create()创建RangeMap,然后put数据。 key=Range(),value=折扣值。

其中:Range有多个方法,注意根据需求使用。

方法左边右边数学表达
open(a, b)
closed[a, b]
closedOpen[a, b)
openClosed(a, b]
/**  
 * the RangeTest 
 * @author Java实用技术手册  
 * @date 2022-12-17  
 */
public class RangeTest {  

 private static RangeMap<Integer, Discount> rangeMap = TreeRangeMap.create();  
   
 public static void main(String[] args) {  
     initDiscountMapGuava();  
     System.out.println("getDiscountGuava_11=" + getDiscountGuava(11));  
     System.out.println("getDiscountGuava_12=" + getDiscountGuava(12));  
 } 
  
    /**  
  * 初始化RangeMap,注意key的区间开闭性。  
  */
 public static void initDiscountMapGuava() {  
     rangeMap.put(Range.closedOpen(0, 12), Discount.DISCOUNT_7);  
     rangeMap.put(Range.closedOpen(12, 18), Discount.DISCOUNT_8);  
     rangeMap.put(Range.closedOpen(18, 24), Discount.DISCOUNT_9);  
 }  
 
 public static Discount getDiscountGuava(Integer time) {  
     return rangeMap.get(Objects.requireNonNull(time));  
 }
}

使用RangeMap后,新增一个时间区间优惠券,只要在初始化方法中增加一行数据,而且key的Range设计也比较符合人文理解。

对RangeMap的遍历,可以使用 Map<Range<K>, V> asMapOfRanges()方法。

以上就是本期内容,希望对你有帮助。

“ 我是Pandas,专注Java编程实用技术分享,公众号《Java实用技术手册》和B站均有视频解说,欢迎来玩。

如果你觉得这篇文章有用,别忘了点赞+关注,一起进步!