Predicate in Java 8: A predicate is a function that takes a single argument and returns a boolean value. In Java, the Predicate interface was introduced in version 1.8 specifically for this purpose, as part of the java.util.function package. This interface serves as a functional interface, designed with a single abstract method: test().
Predicate Interface
The Predicate interface is defined as follows:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
This interface allows the use of lambda expressions, making it highly suitable for functional programming practices.
Example 1: Checking if an Integer is Even
Let’s illustrate this with a simple example of checking whether an integer is even:
Traditional Approach:
public boolean test(Integer i) {
return i % 2 == 0;
}
Lambda Expression:
Predicate<Integer> isEven = i -> i % 2 == 0;
System.out.println(isEven.test(4)); // Output: true
System.out.println(isEven.test(7)); // Output: false
Complete Predicate Program Example:
import java.util.function.Predicate;
public class TestPredicate {
public static void main(String[] args) {
Predicate<Integer> isEven = i -> i % 2 == 0;
System.out.println(isEven.test(4)); // Output: true
System.out.println(isEven.test(7)); // Output: false
// System.out.println(isEven.test(true)); // Compile-time error
}
}
More Predicate Examples
Example 2: Checking String Length
Here’s how you can determine if the length of a string exceeds a specified length:
Predicate<String> isLengthGreaterThanFive = s -> s.length() > 5;
System.out.println(isLengthGreaterThanFive.test("Generate")); // Output: true
System.out.println(isLengthGreaterThanFive.test("Java")); // Output: false
Example 3: Checking Collection Emptiness
You can also check if a collection is not empty using a predicate:
import java.util.Collection;
import java.util.function.Predicate;
Predicate<Collection<?>> isNotEmpty = c -> !c.isEmpty();
Combining Predicates
Predicates can be combined using logical operations such as and()
, or()
, and negate()
. This allows for building more complex conditions.
Example 4: Combining Predicates
Here’s an example demonstrating how to combine predicates:
import java.util.function.Predicate;
public class CombinePredicates {
public static void main(String[] args) {
int[] numbers = {0, 5, 10, 15, 20, 25, 30};
Predicate<Integer> isGreaterThan10 = i -> i > 10;
Predicate<Integer> isOdd = i -> i % 2 != 0;
System.out.println("Numbers greater than 10:");
filterNumbers(isGreaterThan10, numbers);
System.out.println("Odd numbers:");
filterNumbers(isOdd, numbers);
System.out.println("Numbers not greater than 10:");
filterNumbers(isGreaterThan10.negate(), numbers);
System.out.println("Numbers greater than 10 and odd:");
filterNumbers(isGreaterThan10.and(isOdd), numbers);
System.out.println("Numbers greater than 10 or odd:");
filterNumbers(isGreaterThan10.or(isOdd), numbers);
}
public static void filterNumbers(Predicate<Integer> predicate, int[] numbers) {
for (int number : numbers) {
if (predicate.test(number)) {
System.out.println(number);
}
}
}
}
Predicate in Java 8: Using and()
, or()
, and negate()
Methods
In Java programming, the Predicate
interface from the java.util.function
package offers convenient methods to combine and modify predicates, allowing developers to create more sophisticated conditions.
Example 1: Combining Predicates with and()
The and()
method enables the combination of two predicates. It creates a new predicate that evaluates to true only if both original predicates return true.
import java.util.function.Predicate;
public class CombinePredicatesExample {
public static void main(String[] args) {
Predicate<Integer> isGreaterThan10 = i -> i > 10;
Predicate<Integer> isEven = i -> i % 2 == 0;
// Combined predicate: numbers greater than 10 and even
Predicate<Integer> isGreaterThan10AndEven = isGreaterThan10.and(isEven);
// Testing the combined predicate
System.out.println("Combined Predicate Test:");
System.out.println(isGreaterThan10AndEven.test(12)); // Output: true
System.out.println(isGreaterThan10AndEven.test(7)); // Output: false
System.out.println(isGreaterThan10AndEven.test(9)); // Output: false
}
}
Example 2: Combining Predicates with or()
The or()
method allows predicates to be combined so that the resulting predicate returns true if at least one of the original predicates evaluates to true.
import java.util.function.Predicate;
public class CombinePredicatesExample {
public static void main(String[] args) {
Predicate<Integer> isEven = i -> i % 2 == 0;
Predicate<Integer> isDivisibleBy3 = i -> i % 3 == 0;
// Combined predicate: numbers that are either even or divisible by 3
Predicate<Integer> isEvenOrDivisibleBy3 = isEven.or(isDivisibleBy3);
// Testing the combined predicate
System.out.println("Combined Predicate Test:");
System.out.println(isEvenOrDivisibleBy3.test(6)); // Output: true
System.out.println(isEvenOrDivisibleBy3.test(9)); // Output: true
System.out.println(isEvenOrDivisibleBy3.test(7)); // Output: false
}
}
Example 3: Negating a Predicate with negate()
The negate()
method returns a predicate that represents the logical negation (opposite) of the original predicate.
import java.util.function.Predicate;
public class NegatePredicateExample {
public static void main(String[] args) {
Predicate<Integer> isEven = i -> i % 2 == 0;
// Negated predicate: numbers that are not even
Predicate<Integer> isNotEven = isEven.negate();
// Testing the negated predicate
System.out.println("Negated Predicate Test:");
System.out.println(isNotEven.test(3)); // Output: true
System.out.println(isNotEven.test(6)); // Output: false
}
}
and()
Method: Combines two predicates so that both conditions must be true for the combined predicate to return true.
or()
Method: Creates a predicate that returns true if either of the two predicates is true.
negate()
Method: Returns a predicate that represents the logical negation (inverse) of the original predicate.
Best Practices for Using Predicate in Java 8
- Descriptive Names: Use descriptive variable names for predicates to enhance code readability (e.g.,
isEven
,isLengthGreaterThanFive
). - Conciseness: Keep lambda expressions concise and avoid complex logic within them.
- Combination: Utilize
and()
,or()
, andnegate()
methods to compose predicates for more refined conditions. - Stream Operations: Predicates are commonly used in stream operations for filtering elements based on conditions.
- Null Handling: Consider null checks if predicates may encounter null values.
- Documentation: Document predicates, especially those with complex logic, to aid understanding for others and future reference.
Conclusion
Predicates in Java provide a powerful mechanism for testing conditions on objects, offering flexibility and efficiency in code design. By leveraging lambda expressions and method references, developers can write cleaner and more expressive code. Start incorporating predicates into your Java projects to streamline logic and improve maintainability.