Java 8 | Predicate

Predicate 是“断言”的意思。就是给你一段描述,判断这段描述是正确的还是错误的。这就像我们考试中做的判断题一样。

在编程中,我们经常会有这样的操作。当我们有一个集合,我们需要筛选出符合我们要求的一部分,抛弃不符合的那部分。

详细的例子就是,当我们拿到一份学成成绩单,我们需要获取那些60分以上的学生名单。

List<Integer> scores = Arrays.asList(40, 55, 59 , 69, 80);
List<Integer> passing = new ArrayList();

for (Integer score : scores) {
  if (score >= 60) {
    passing.add(score);
  }
}

但是 Java 8 带来了 Lambda 表达式,我们现在完成这个功能只需要一行代码

List<Integer> passing  = scores.stream().filter((score) -> score >= 60).collect(Collectors.toList());

其中 filter 方法中接受的参数就是 PredicatePredicate 在 lambda 表达式中作为判断条件很是常用,下面我们来深入了解一下 Predicate

首先 Predicate 是一个函数式接口,这就意味着 Predicate 可以用一个 Lambda 表达式来表示。正如上面 filter() 方法传递的那样。

/**
 * Returns a stream consisting of the elements of this stream that match
 * the given predicate.
 *
 * <p>This is an <a href="package-summary.html#StreamOps">intermediate
 * operation</a>.
 *
 * @param predicate a non-interfering stateless predicate to apply to each element to determine if it
 * should be included in the new returned stream.
 * @return the new stream
 */
Stream<T> filter(Predicate<? super T> predicate);

Streams 我们后面再介绍,这里我们可以把它当做是一个“集合”,我们可以对这个“集合”做某些操作。让我们看看一些例子。

在集合中使用 Predicate

定义一个 Employee

public class Employee {
    
   public Employee(Integer id, Integer age, String gender, String fName, String lName){
       this.id = id;
       this.age = age;
       this.gender = gender;
       this.firstName = fName;
       this.lastName = lName;
   }
     
   private Integer id;
   private Integer age;
   private String gender;
   private String firstName;
   private String lastName;
 
   //Please generate Getter and Setters
 
    @Override
    public String toString() {
        return this.id.toString()+" - "+this.age.toString(); //To change body of generated methods, choose Tools | Templates.
    }
}
  1. 年龄大于21的男性员工
public static Predicate<Employee> isAdultMale() {
    return p -> p.getAge() > 21 && p.getGender().equalsIgnoreCase("M");
}
  1. 年龄大于 18 的女性员工
public static Predicate<Employee> isAdultFemale() {
    return p -> p.getAge() > 18 && p.getGender().equalsIgnoreCase("F");
}
  1. 年龄大于指定年龄的员工
public static Predicate<Employee> isAgeMoreThan(Integer age) {
    return p -> p.getAge() > age;
}

我们可以具体的过滤条件条件常见不同的 Predicate。

public class EmployeePredicates {
    public static Predicate<Employee> isAdultMale() {
        return p -> p.getAge() > 21 && p.getGender().equalsIgnoreCase("M");
    }
     
    public static Predicate<Employee> isAdultFemale() {
        return p -> p.getAge() > 18 && p.getGender().equalsIgnoreCase("F");
    }
     
    public static Predicate<Employee> isAgeMoreThan(Integer age) {
        return p -> p.getAge() > age;
    }
     
    public static List<Employee> filterEmployees (List<Employee> employees, Predicate<Employee> predicate) {
        return employees.stream().filter( predicate ).collect(Collectors.<Employee>toList());
    }
}  

这样使得我们的代码更加简洁

public class TestEmployeePredicates {
    public static void main(String[] args){
        Employee e1 = new Employee(1,23,"M","Rick","Beethovan");
        Employee e2 = new Employee(2,13,"F","Martina","Hengis");
        Employee e3 = new Employee(3,43,"M","Ricky","Martin");
        Employee e4 = new Employee(4,26,"M","Jon","Lowman");
        Employee e5 = new Employee(5,19,"F","Cristine","Maria");
        Employee e6 = new Employee(6,15,"M","David","Feezor");
        Employee e7 = new Employee(7,68,"F","Melissa","Roy");
        Employee e8 = new Employee(8,79,"M","Alex","Gussin");
        Employee e9 = new Employee(9,15,"F","Neetu","Singh");
        Employee e10 = new Employee(10,45,"M","Naveen","Jain");
         
        List<Employee> employees = new ArrayList<Employee>();
        employees.addAll(Arrays.asList(new Employee[]{e1,e2,e3,e4,e5,e6,e7,e8,e9,e10}));
                
        System.out.println(filterEmployees(employees, isAdultMale()));
         
        System.out.println(filterEmployees(employees, isAdultFemale()));
         
        System.out.println(filterEmployees(employees, isAgeMoreThan(35)));
         
        //Employees other than above collection of "isAgeMoreThan(35)" can be get using negate()
        System.out.println(filterEmployees(employees, isAgeMoreThan(35).negate()));
    }
}
 
Output:
 
[1 - 23, 3 - 43, 4 - 26, 8 - 79, 10 - 45]
[5 - 19, 7 - 68]
[3 - 43, 7 - 68, 8 - 79, 10 - 45]
[1 - 23, 2 - 13, 4 - 26, 5 - 19, 6 - 15, 9 - 15]

关于 Predicate 的一些思考

  1. Predicate 使得将一些条件(或者业务逻辑)统一到一个地方进行管理,方便单元测试
  2. 统一管理是的修改也更加方便了
  3. 可读性更强了,filterEmployees(employees, isAdultFemale()) 更容易理解,而且不再是 if-else 的代码块了
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java 8 lambda 表达式10个示例 Java 8 发布于4年前,日期是2014年3月18日,这次开创性的...
    认真期待阅读 5,216评论 2 6
  • 第一章 为什么要关心Java 8 使用Stream库来选择最佳低级执行机制可以避免使用Synchronized(同...
    谢随安阅读 5,357评论 0 4
  • 惟愿她安好 作者 刘淑雨 想念着童年里的单车,记忆里的阳光,妈...
    改变自己369阅读 2,224评论 0 4
  • 当今中国大多数男人的想法都还停留在男主外女主内的思想上,可真的男主外女主内后,男人又会觉得自己付出的比女人多,他的...
    668744ddca79阅读 2,905评论 0 0
  • 爱美之心,人皆有之。很多女性朋友需要在美容上面花很多的钱,实际上站在我的角度来说,由内而外的美才是真正的美。身体里...
    金葉艾灸阅读 4,007评论 0 1