# Java 谓词示例 – 谓词过滤器

> 原文： [https://howtodoinjava.com/java8/how-to-use-predicate-in-java-8/](https://howtodoinjava.com/java8/how-to-use-predicate-in-java-8/)

在数学中，**谓词**通常被理解为**布尔值函数**`'P: X? {true, false}'`，称为`X`谓词。 可以将其视为返回`true`或`false`值的运算符或函数。

## Java 8 谓词用法

在 Java 8 中，[谓词](https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html)是[函数式接口](https://howtodoinjava.com/java8/functional-interface-tutorial/)，因此可以用作 [**lambda 表达式**](//howtodoinjava.com/java8/complete-lambda-expressions-tutorial-in-java/ "Complete lambda expressions tutorial") 或方法参考的分配目标。 那么，您认为如何，我们可以在日常编程中使用这些`true`/`false`返回函数？ 我会说，您可以在需要求值类似对象的组/集合上的条件的任何地方使用谓词，以便求值可以得出`true`或`false`。

例如，您可以在这些**实时用例**中使用谓词：

1.  查找在特定日期之后出生的所有孩子
2.  特定时间定下的披萨
3.  超过一定年龄的员工等

#### Java 谓词类

因此， **java 谓词**似乎很有趣。 让我们更深入。

如我所说，`Predicate`是**函数式接口**。 这意味着我们可以在需要谓词的任何地方传递 lambda 表达式。 例如，一种这样的方法是来自[**流**](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html)接口的`filter()`方法。

```java
/**
 * 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);

```

我们可以将流假定为一种机制，以创建支持顺序和并行聚合操作的元素序列。 这意味着我们可以随时通过一次调用收集并执行流中存在的所有元素的某些操作。

因此，从本质上讲，我们可以使用流和谓词来：

*   首先从组中过滤某些元素，然后
*   然后对过滤后的元素执行一些操作。

## 在集合上使用谓词

为了演示，我们有一个`Employee`类，如下所示：

```java
package predicateExample;

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

   //To change body of generated methods, choose Tools | Templates.
    @Override
    public String toString() {
        return this.id.toString()+" - "+this.age.toString(); 
    }
}

```

#### 1\. 所有年龄在 21 岁以上的男性员工

```java
public static Predicate<Employee> isAdultMale() 
{
    return p -> p.getAge() > 21 && p.getGender().equalsIgnoreCase("M");
}

```

#### 2\. 所有年龄在 18 岁以上的女性员工

```java
public static Predicate<Employee> isAdultFemale() 
{
    return p -> p.getAge() > 18 && p.getGender().equalsIgnoreCase("F");
}

```

#### 3\. 所有年龄超过给定年龄的员工

```java
public static Predicate<Employee> isAgeMoreThan(Integer age) 
{
    return p -> p.getAge() > age;
}

```

您可以在需要时构建更多它们。 到目前为止，一切都很好。 到目前为止，我已经在`EmployeePredicates.java`中包括了上述 3 种方法：

```java
package predicateExample;

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

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());
    }
}   

```

您会看到我创建了另一个工具方法`filterEmployees()`，以显示 **java 谓词过滤器**。 基本上是使代码整洁并减少重复。 您也可以编写多个谓词来构成**谓词链**，就像在[构建器模式](https://howtodoinjava.com/design-patterns/creational/builder-pattern-in-java/)中所做的那样。

因此，在此函数中，我们传递`employees`的列表并传递谓词，然后此函数将返回满足**参数谓词**中提到的条件的`employees`的新集合。

```java
package predicateExample;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static predicateExample.EmployeePredicates.*;

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]

```

谓词在 Java 8 中确实是非常好的添加，只要有机会，我都会使用它。

## 关于 Java 8 中谓词的最终思考

1.  他们将您的条件（有时是业务逻辑）转移到中心位置。 这有助于分别对它们进行单元测试。
2.  无需将任何更改复制到多个位置。 Java 谓词改善了代码维护。
3.  代码例如“`filterEmployees(employees, isAdultFemale())`”比编写`if-else`块更具可读性。

好的，这些是我在 Java 8 谓词中的想法。 您如何看待此特性？ 在评论部分与我们所有人分享。

学习愉快！

阅读更多 ：

[Java 谓词取反示例](https://howtodoinjava.com/java8/predicate-negate-example/)

[Java 链接谓词 – 逻辑 AND 和逻辑 OR 运算](https://howtodoinjava.com/java8/predicates-logical-operations/)