ZetCode

Java Predicate 接口

最后修改时间:2025 年 4 月 16 日

java.util.function.Predicate 接口表示一个布尔值函数,用于测试条件。它是一个函数式接口,只有一个抽象方法 test。Predicate 常用于过滤集合和流。

Predicate 在 Java 8 中引入,并在 JDK 9 中通过新方法进行了增强。它支持函数式编程风格中的条件逻辑。该接口提供了用于逻辑运算和谓词组合的方法。

Predicate 接口概述

Predicate 接口包含一个抽象方法和几个默认和静态方法。关键方法 test 用于评估条件。其他方法支持谓词的逻辑组合。

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
    
    default Predicate<T> and(Predicate<? super T> other);
    default Predicate<T> or(Predicate<? super T> other);
    default Predicate<T> negate();
    static <T> Predicate<T> not(Predicate<? super T> target);
    static <T> Predicate<T> isEqual(Object targetRef);
}

以上代码展示了 Predicate 接口的结构。它使用泛型,其中 T 是输入类型。该接口使用 @FunctionalInterface 注解来表明其单一抽象方法的性质。

Predicate 的基本用法

使用 Predicate 最简单的方式是使用 lambda 表达式。我们在 test 方法中定义要测试的条件。示例检查数字是否为偶数。

Main.java
package com.zetcode;

import java.util.function.Predicate;

public class Main {

    public static void main(String[] args) {

        // Define a predicate that tests if number is even
        Predicate<Integer> isEven = n -> n % 2 == 0;
        
        // Test the predicate
        System.out.println("Is 4 even? " + isEven.test(4));
        System.out.println("Is 7 even? " + isEven.test(7));
        
        // Predicate using method reference
        Predicate<String> isEmpty = String::isEmpty;
        System.out.println("Is empty? " + isEmpty.test(""));
    }
}

此示例演示了使用 lambda 和方法引用的 Predicate 基本用法。isEven 谓词接受 Integer 并返回 boolean。我们用不同的数字来测试它。方法引用为现有方法提供了简洁的语法。

使用 and() 的 Predicate 组合

and 方法使用逻辑 AND 组合两个谓词。生成的谓词仅当两个原始谓词都测试为真时才测试为真。这使复杂条件可以由简单谓词构成。

Main.java
package com.zetcode;

import java.util.function.Predicate;

public class Main {

    public static void main(String[] args) {

        // First predicate checks if number is positive
        Predicate<Integer> isPositive = n -> n > 0;
        
        // Second predicate checks if number is even
        Predicate<Integer> isEven = n -> n % 2 == 0;
        
        // Combine predicates with AND
        Predicate<Integer> isPositiveAndEven = isPositive.and(isEven);
        
        System.out.println("6 is positive and even? " + isPositiveAndEven.test(6));
        System.out.println("-2 is positive and even? " + isPositiveAndEven.test(-2));
        System.out.println("3 is positive and even? " + isPositiveAndEven.test(3));
    }
}

此示例展示了使用 and 的谓词组合。组合后的谓词测试既是正数又是偶数的数字。在我们的测试用例中,只有 6 满足这两个条件。

使用 or() 的 Predicate 组合

or 方法使用逻辑 OR 组合两个谓词。当任一原始谓词测试为真时,生成的谓词测试为真。这对于测试多个可能的条件很有用。

Main.java
package com.zetcode;

import java.util.function.Predicate;

public class Main {

    public static void main(String[] args) {

        // First predicate checks if string starts with 'A'
        Predicate<String> startsWithA = s -> s.startsWith("A");
        
        // Second predicate checks if string ends with 'e'
        Predicate<String> endsWithE = s -> s.endsWith("e");
        
        // Combine predicates with OR
        Predicate<String> startsOrEnds = startsWithA.or(endsWithE);
        
        System.out.println("Apple: " + startsOrEnds.test("Apple"));
        System.out.println("Orange: " + startsOrEnds.test("Orange"));
        System.out.println("Banana: " + startsOrEnds.test("Banana"));
    }
}

此示例演示了使用 or 的谓词组合。组合后的谓词测试以 'A' 开头或以 'e' 结尾的字符串。“Apple” 满足这两个条件,“Orange” 满足结尾条件。

使用 negate() 的 Predicate 取反

negate 方法返回一个谓词,该谓词表示原始谓词的逻辑否定。这等同于逻辑 NOT 运算。

Main.java
package com.zetcode;

import java.util.function.Predicate;

public class Main {

    public static void main(String[] args) {

        // Predicate checks if number is greater than 10
        Predicate<Integer> greaterThan10 = n -> n > 10;
        
        // Create negated version
        Predicate<Integer> notGreaterThan10 = greaterThan10.negate();
        
        System.out.println("Is 15 > 10? " + greaterThan10.test(15));
        System.out.println("Is 15 not > 10? " + notGreaterThan10.test(15));
        System.out.println("Is 5 not > 10? " + notGreaterThan10.test(5));
    }
}

此示例展示了使用 negate 的谓词取反。取反后的谓词返回原始谓词的相反布尔值。15 大于 10,因此其否定返回 false。

JDK 9+ not() 静态方法

JDK 9 引入了静态 not 方法,作为 negate 的替代方案。它创建一个谓词,该谓词是对提供的谓词的否定。这对于方法引用很有用。

Main.java
package com.zetcode;

import java.util.function.Predicate;
import java.util.List;
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {

        List<String> names = Arrays.asList("Alice", "Bob", "", "Charlie", "");
        
        // Filter non-empty strings using not()
        Predicate<String> nonEmpty = Predicate.not(String::isEmpty);
        
        long count = names.stream()
            .filter(nonEmpty)
            .count();
            
        System.out.println("Non-empty names: " + count);
    }
}

此示例演示了 JDK 9 的 not 方法。我们创建一个谓词,通过否定 isEmpty 来检查非空字符串。流使用此谓词过滤掉空字符串。结果计算非空名称。

使用 isEqual() 的 Predicate 组合

静态 isEqual 方法创建一个谓词,该谓词测试输入是否等于目标对象。它使用 Objects.equals() 进行比较,安全地处理 null 值。

Main.java
package com.zetcode;

import java.util.function.Predicate;
import java.util.List;
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {

        // Create predicate that tests for "admin"
        Predicate<String> isAdmin = Predicate.isEqual("admin");
        
        List<String> users = Arrays.asList("user1", "admin", "user2", "admin");
        
        long adminCount = users.stream()
            .filter(isAdmin)
            .count();
            
        System.out.println("Admin users: " + adminCount);
        
        // Works with null values
        Predicate<String> isNull = Predicate.isEqual(null);
        System.out.println("Is null? " + isNull.test(null));
    }
}

此示例展示了 isEqual 的用法。我们创建一个谓词来查找列表中 "admin" 用户。流计算匹配的条目。该示例还演示了 null 安全比较。

复杂的 Predicate 组合

谓词可以使用多种组合方式进行复杂组合。此示例展示了结合 and()、or() 和 negate() 来创建复杂的条件。

Main.java
package com.zetcode;

import java.util.function.Predicate;

public class Main {

    public static void main(String[] args) {

        Predicate<Integer> isEven = n -> n % 2 == 0;
        Predicate<Integer> isPositive = n -> n > 0;
        Predicate<Integer> isMultipleOf3 = n -> n % 3 == 0;
        
        // Complex predicate: (positive AND even) OR (multiple of 3)
        Predicate<Integer> complexPredicate = 
            isPositive.and(isEven).or(isMultipleOf3);
            
        System.out.println("4: " + complexPredicate.test(4));  // true (pos+even)
        System.out.println("-6: " + complexPredicate.test(-6)); // true (multiple of 3)
        System.out.println("5: " + complexPredicate.test(5));  // false
        System.out.println("9: " + complexPredicate.test(9));  // true (multiple of 3)
    }
}

此示例创建了一个复杂的谓词,结合了多个条件。该谓词对 (正数且为偶数) 或 (3 的倍数) 的数字测试为真。这展示了强大的谓词组合功能。

来源

Java Predicate 接口文档

在本文中,我们涵盖了 Java Predicate 接口的基本方法和特性,重点介绍了 JDK 9+ 的增强功能。理解这些概念对于函数式编程和流处理至关重要。

作者

我叫 Jan Bodnar,是一位经验丰富的程序员。我于 2007 年开始撰写编程文章,至今已撰写了 1400 多篇文章和 8 本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程