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.