Predicate Functional Interface in Java 8 with Examples

In Java 8, Predicate Functional Interface is one of the built-in functional interfaces that can be used for defining a lambda expression. A Predicate is a functional interface that represents a function that takes in a single argument and returns a boolean value.

Table of Content :

The Predicate functional interface has a single abstract method named "test" which takes in an object of the specified type and returns a boolean value. The test() method evaluates the boolean condition on the object passed as input and returns true or false accordingly.

The syntax of the Predicate functional interface is as follows:

@FunctionalInterface public interface Predicate<T> { boolean test(T t); }


package com.javacodestuffs.core.java.functional.iface; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; public class PredicateExample { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(21, 42, 63, 84, 105, 126, 147, 168, 189, 210); Predicate<Integer> evenPredicate = (n) -> (n % 2 == 0); List<Integer> evenNumbers = numbers.stream().filter(evenPredicate).collect(Collectors.toList()); System.out.println("The even Numbers are: "); System.out.println(evenNumbers); } }

Output:

The even Numbers are: [42, 84, 126, 168, 210]

In the above code, the evenPredicate lambda expression takes in an Integer object and returns a boolean value. The filter() method of the Stream class then uses the evenPredicate to filter out only the even numbers from the list of integers.

The Predicate functional interface is a useful tool in Java 8 that can simplify code and make it more readable. It is often used in conjunction with other built-in functional interfaces like Consumer, Function, and Supplier.

Predicate Functional Interface use cases

Here are a few examples of how the Predicate Functional Interface can be used in Java 8:

1. Filtering a List: You can use a Predicate to filter a list of objects based on a specific condition. For example, let's say you have a list of strings and you want to filter out all the strings that start with the letter "A". You can use the following code:

List<String> strings = Arrays.asList("Apple", "Banana", "Apricot", "Cherry", "Mango"); Predicate<String> startsWithAPredicate = (s) -> s.startsWith("A"); List<String> filteredStrings = strings.stream().filter(startsWithAPredicate).collect(Collectors.toList());

In this example, the Predicate checks if the string starts with the letter "A" and returns a boolean value. The filter() method of the Stream class then uses this Predicate to filter out all the strings that do not match the condition.

2. Combining Predicates: You can also combine multiple Predicates to create more complex conditions. For example, let's say you want to filter out all the strings that start with the letter "A" and have more than 5 characters. You can use the following code:

Predicate<String> startsWithAPredicate = (s) -> s.startsWith("A"); Predicate<String> moreThan5CharsPredicate = (s) -> s.length() > 5; Predicate<String> combinedPredicate = startsWithAPredicate.and(moreThan5CharsPredicate); List<String> filteredStrings = strings.stream().filter(combinedPredicate).collect(Collectors.toList());

In this example, we create two separate Predicates for each condition and then combine them using the and() method of the Predicate interface. The resulting Predicate only returns true if both conditions are met.

3. Validating Input: Predicates can also be used for input validation. For example, let's say you want to validate that a given string is a valid email address. You can use the following code:

String email = "johndoe@example.com"; Predicate<String> emailValidator = (s) -> s.matches("\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z]{2,}\\b"); boolean isValid = emailValidator.test(email);

In this example, the Predicate checks if the string matches a specific regular expression pattern that is commonly used to validate email addresses. The test() method of the Predicate interface then returns true if the string matches the pattern.

Advantages to use Predicate Functional Interface

There are several advantages to using the Predicate Functional Interface in Java 8:

  • Simplified Code: Using a Predicate can make your code more concise and readable by allowing you to express boolean conditions in a compact and clear way. This can reduce code clutter and make it easier to understand and maintain.
  • Flexibility: Predicates are versatile and can be used in many different scenarios. They can be used in conjunction with other functional interfaces, such as Consumer and Function, to create complex and powerful functional pipelines.
  • Reusability: Predicates can be reused across different parts of your codebase, as they are independent functions that can be passed as arguments to other methods. This can save time and effort by reducing the need for redundant code.
  • Improved Performance: Predicates can be used with Java 8's Stream API to efficiently process large collections of data in parallel. This can lead to significant performance improvements compared to traditional looping constructs.
  • Type Safety: Predicates are strongly typed, which means that the type of the argument passed to the test() method is known at compile time. This can help to prevent errors and improve the reliability of your code.

Overall, the Predicate Functional Interface provides a powerful and flexible tool for expressing boolean conditions in Java 8. By using Predicates, you can simplify your code, improve performance, and increase the reliability and maintainability of your applications.

Conclusion

Overall, the Predicate Functional Interface in Java 8 provides a powerful and flexible way to define behavior as a parameter to methods, making Java code more modular, reusable, and performant.