java8中的 Predicate && Consumer
最近在看一個(gè)開(kāi)源項(xiàng)目,發(fā)現(xiàn)代碼用了很多jdk8的lambda特性。特來(lái)學(xué)習(xí)總結(jié)一下常用的Predicate和Consumer
Predicate
Predicate用于判斷輸入?yún)?shù)是否滿足某一個(gè)條件,為了更方便地解釋?zhuān)覀兿咕幰粋€(gè)例子
需求: 有一組成績(jī)數(shù)據(jù),要求統(tǒng)計(jì)出所有及格的分?jǐn)?shù)列表。
這個(gè)簡(jiǎn)單,我們隨便寫(xiě)一下就出來(lái)了
List<Integer> passList = scoreList.stream()
.filter(s -> s >= 60 && s <= 100)
.collect(Collectors.toList());
這個(gè)時(shí)候又來(lái)了一個(gè)新需求,要求統(tǒng)計(jì)出所有及格的,并且分?jǐn)?shù)是奇數(shù)的列表,要怎么寫(xiě)?
List<Integer> passOddList = scoreList.stream()
.filter(s -> s >= 60 && s < 100 && s % 2 == 1)
.collect(Collectors.toList());
這個(gè)時(shí)候又來(lái)了一個(gè)新需求,要統(tǒng)計(jì)出所有不及格的分?jǐn)?shù)列表呢?
List<Integer> failedList = scoreList.stream()
.filter(s -> s < 60)
.collect(Collectors.toList());
可以看到判斷及格的邏輯被重復(fù)寫(xiě)了好幾遍,如果想盡量復(fù)用應(yīng)該怎么寫(xiě)?答案是把判斷及格的邏輯抽出來(lái),
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());
}
可以看到我們不僅把各種判斷條件抽取了出來(lái),作為單獨(dú)的Predicate方法,還把“選取分?jǐn)?shù)”的模式也抽象出來(lái)了。對(duì)于再有新的過(guò)濾分?jǐn)?shù)的需求,只需要新增具體的Predicate,就可以做各種組合。
Consumer
Consumer會(huì)接受單個(gè)輸入?yún)?shù),并且可能對(duì)參數(shù)值進(jìn)行修改。把“操作”提取成為一個(gè)“操作模式”,可以盡可能地代碼復(fù)用。對(duì)于Consumer,我會(huì)把它理解為excel中的一個(gè)“公式“,滿足條件的某列,都可以應(yīng)用這個(gè)公式生成一個(gè)新的值。
Predicate && Consumer一般會(huì)配合使用, 主要應(yīng)用于這種場(chǎng)景,如果參數(shù)滿足某條件,則對(duì)參數(shù)做某操作。為了更好地說(shuō)明,讓我們?cè)賮?lái)瞎編一個(gè)例子。
需求:又到了一年一度的加薪日,L1的員工每人加薪20%,L2的員工每人加薪15%,使用lambda怎么寫(xiě)
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 +
'}';
}
}
}