Predicate-代码简洁之道

Predicate是Java 8增加的特性,中文翻译为(谓词;使基于,使取决于;表明,断言)。中文意思应该是,“因为今天刮台风,所以小明不用去上学”。这句话中的原因,即Predicate=原因(条件)。
任何代码逻辑都少不了IF判断(或SwitchFor等),为了写出更简洁明了的代码,便可以将这些判断中的条件抽象成PredicatePredicate的输出结果只有TRUEFALSE两种。
例如:

1
2
3
// 判断给定的小时数字,是否在1到3天之间
Predicate<Long> isEvent = hours -> (hours > 24 && hours < 24 * 3);
isEvent.test(20L);

我们也知道,在Java 8 的特性中,有着另一种用于处理空指针异常的方式:Optional,它也是一种判断条件的抽象表示,更适用于null值的处理操作,经常在代码行内使用,例如:

1
2
3
4
5
public void test(List<Long> list){
List<Long> longs = Optional.of(list).orElse(new ArrayList<>());
longs.add(1L);
System.out.println(longs);
}

Predicate经常会当做一个方法的参数进行传递,例如:账号过期提醒规则,剩余1个月有效期则每周提醒一次,剩余7天内有效期则每天提醒一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public void userTask{
@Autowired
private UserService userService;

@Scheduled(cron = "0 0 3 * * ?")
public void dayInform() {
Predicate<Long> event= hours -> (hours > 8 && hours < 24 * 7);
checkAccountEffective(isEvent, "每天定时提醒");
}

@Scheduled(cron = "0 0 3 ? * 1")
public void weekInform() {
Predicate<Long> event= hours -> (hours > 24 * 7 && hours < 24 * 30);
checkEffectiveTime(event, "每周定时提醒");
}

private void checkEffectiveTime(Predicate<Long> event, String task) {
List<User> users = userService.list();
List<MessageSend> messages = new ArrayList<>();
LocalDateTime now = LocalDateTime.now();
users.forEach(user -> {
LocalDateTime expiryTime = user.getExpiryTime();
if (expiryTime == null || now.isAfter(expiryTime)) {
return;
}
long hours = Duration.between(now, expiryTime).toHours();
if (event.test(hours)) {
String message = "尊敬的用户,您的账号将在%s到期,请及时处理。";
MessageSend msg= MessageSend(message.formatted(expiryDate.toLocalDate().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"))), user.getId(),task);
messages.add(msg);
}
});
userService.sendMessage(messages);
}
}

上面的代码,便是将IF判断条件抽象成Preditace,避免了编写重复代码。