java8中的 Predicate && Consumer
最近在看一个开源项目,发现代码用了很多jdk8的lambda特性。特来学习总结一下常用的Predicate和Consumer
Predicate
Predicate用于判断输入参数是否满足某一个条件,为了更方便地解释,我们瞎编一个例子
需求: 有一组成绩数据,要求统计出所有及格的分数列表。
这个简单,我们随便写一下就出来了
List<Integer> passList = scoreList.stream()
.filter(s -> s >= 60 && s <= 100)
.collect(Collectors.toList());
这个时候又来了一个新需求,要求统计出所有及格的,并且分数是奇数的列表,要怎么写?
List<Integer> passOddList = scoreList.stream()
.filter(s -> s >= 60 && s < 100 && s % 2 == 1)
.collect(Collectors.toList());
这个时候又来了一个新需求,要统计出所有不及格的分数列表呢?
List<Integer> failedList = scoreList.stream()
.filter(s -> s < 60)
.collect(Collectors.toList());
可以看到判断及格的逻辑被重复写了好几遍,如果想尽量复用应该怎么写?答案是把判断及格的逻辑抽出来,
public static void main(String[] args) {
List<Integer> passList = filter(scoreList, passPredicate());
List<Integer> failedList = filter(scoreList, passPredicate().negate());
List<Integer> passOddList = filter(scoreList, passPredicate().and(isOdd()));
}
private static Predicate<Integer> passPredicate() {
return x -> (x >= 60 && x <= 100);
}
private static Predicate<Integer> isOdd() {
return x -> x % 2 == 1;
}
private static List<Integer> filter(List<Integer> originalList, Predicate<Integer> predicate) {
return originalList.stream().filter(predicate).collect(Collectors.toList());
}
可以看到我们不仅把各种判断条件抽取了出来,作为单独的Predicate方法,还把“选取分数”的模式也抽象出来了。对于再有新的过滤分数的需求,只需要新增具体的Predicate,就可以做各种组合。
Consumer
Consumer会接受单个输入参数,并且可能对参数值进行修改。把“操作”提取成为一个“操作模式”,可以尽可能地代码复用。对于Consumer,我会把它理解为excel中的一个“公式“,满足条件的某列,都可以应用这个公式生成一个新的值。
Predicate && Consumer一般会配合使用, 主要应用于这种场景,如果参数满足某条件,则对参数做某操作。为了更好地说明,让我们再来瞎编一个例子。
需求:又到了一年一度的加薪日,L1的员工每人加薪20%,L2的员工每人加薪15%,使用lambda怎么写
public class ConsumerTest {
private static Consumer<User> salaryIncreaseConsumer(double ratio) {
return u -> u.setSalary(u.getSalary() * (1 + ratio));
}
private static Predicate<User> levelPredicate(int level) {
return u -> u.getLevel() == level;
}
public static void main(String[] args) {
User rock = new User("rock", 1, 100);
System.out.println(rock);
if (levelPredicate(1).test(rock)) {
salaryIncreaseConsumer(0.2).accept(rock);
}
System.out.println(rock);
User vivi = new User("vivi", 2, 80);
System.out.println(vivi);
if (levelPredicate(2).test(vivi)) {
salaryIncreaseConsumer(0.15).accept(vivi);
}
System.out.println(vivi);
}
private static class User {
private String name;
private int level;
private double salary;
public User(String name, int level, double salary) {
this.name = name;
this.level = level;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", level=" + level +
", salary=" + salary +
'}';
}
}
}