Java Predicate Interface
Last modified: April 16, 2025
The java.util.function.Predicate
interface represents a boolean-valued
function that tests a condition. It is a functional interface with a single
abstract method test
. Predicate is commonly used for filtering
collections and streams.
Predicate
was introduced in Java 8 and enhanced in JDK 9 with new
methods. It enables conditional logic in functional programming style. The
interface provides methods for logical operations and predicate composition.
Predicate Interface Overview
Predicate
interface contains one abstract method and several default
and static methods. The key method test
evaluates the condition.
Other methods enable logical combinations of predicates.
@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); }
The code above shows the structure of Predicate
interface. It uses
generics where T is the input type. The interface is annotated with
@FunctionalInterface to indicate its single abstract method nature.
Basic Predicate Usage
The simplest way to use Predicate is with lambda expressions. We define the condition to test in the test method. The example checks if numbers are even.
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("")); } }
This example demonstrates basic Predicate usage with lambda and method reference. The isEven predicate takes Integer and returns boolean. We test it with different numbers. Method reference provides concise syntax for existing methods.
Predicate Composition with and()
The and
method combines two predicates with logical AND. The
resulting predicate tests true only when both original predicates test true.
This enables complex conditions from simple predicates.
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)); } }
This example shows predicate composition with and
. The combined
predicate tests for numbers that are both positive and even. Only 6 satisfies
both conditions in our test cases.
Predicate Composition with or()
The or
method combines two predicates with logical OR. The
resulting predicate tests true when either original predicate tests true.
This is useful for testing multiple possible conditions.
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")); } }
This example demonstrates predicate composition with or
. The
combined predicate tests for strings that start with 'A' or end with 'e'.
"Apple" satisfies both conditions, "Orange" satisfies the ending condition.
Predicate Negation with negate()
The negate
method returns a predicate that represents the logical
negation of the original predicate. This is equivalent to the logical NOT
operation.
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)); } }
This example shows predicate negation with negate
. The negated
predicate returns the opposite boolean value of the original. 15 is greater than
10, so its negation returns false.
JDK 9+ not() Static Method
JDK 9 introduced the static not
method as an alternative to
negate
. It creates a predicate that is the negation of the
supplied predicate. This is useful for method references.
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); } }
This example demonstrates JDK 9's not
method. We create a predicate
that checks for non-empty strings by negating isEmpty. The stream filters out
empty strings using this predicate. The result counts non-empty names.
Predicate Composition with isEqual()
The static isEqual
method creates a predicate that tests if the
input equals a target object. It uses Objects.equals() for comparison, handling
null values safely.
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)); } }
This example shows isEqual
usage. We create a predicate to find
"admin" users in a list. The stream counts matching entries. The example also
demonstrates null-safe comparison.
Complex Predicate Composition
Predicates can be combined in complex ways using multiple compositions. This example shows combining and(), or(), and negate() to create sophisticated conditions.
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) } }
This example creates a complex predicate combining multiple conditions. The predicate tests true for numbers that are either (positive and even) or (multiples of 3). This demonstrates powerful predicate composition.
Source
Java Predicate Interface Documentation
In this article, we've covered the essential methods and features of the Java Predicate interface, with focus on JDK 9+ enhancements. Understanding these concepts is crucial for functional programming and stream processing.
Author
List all Java tutorials.