In Depth Explanation of Predicate in Java 8 With Real Time Example :
What is Predicate In Java 8 ?
A Predicate in Java 8 is a functional interface that represents a boolean–valued function of one argument. It’s a powerful tool for filtering and testing elements within collections, making code more concise and readable.
Key Points About Predicate In Java 8 :
- Functional Interface: It has only one abstract method,
test()
. - Boolean Return Type: The
test()
method takes an argument and returns a boolean value. - Filtering and Testing: Predicates are often used to filter elements from collections based on specific criteria.
- Lambda Expressions: Predicates are commonly implemented using lambda expressions, making code more concise and expressive.
Basic Example of Predicate In Java 8:
package com.java8; import java.util.function.Predicate; /** * source : crtr4u.com * Author : Swapnil V */ public class PredicateExample { public static void main(String[] args) { Predicate<Integer> isEvenNumber = num -> num % 2 == 0; System.out.println(isEvenNumber.test(4)); // Output: true System.out.println(isEvenNumber.test(5)); // Output: false } }
Output of Above Program :
true false
Basic Example of Predicate In Java 8
package com.java8; import java.util.Scanner; import java.util.function.Predicate; /** * source : crtr4u.com * Author : Swapnil V */ public class PredicateDemo { public static void main(String[] args) { Integer passingMarks =35; Predicate<Integer> testPassedOrFail=I->(I>=passingMarks); try (Scanner scn = new Scanner(System.in)) { System.out.println("Enter Marks Obtained :"); Integer marksObtained=scn.nextInt(); String result =testPassedOrFail.test(marksObtained)==true ? "Passed Congrats" : "Failed ,Try Again"; System.out.println(result); } } }
Output of Above Program :
Enter Marks Obtained : 44 Passed Congrats --------------------------------------------------------------------------------------- Enter Marks Obtained : 30 Failed ,Try Again
Common Use Cases Of Predicate In Java 8 :
1.Filtering Collection Elements Using Predicate In Java 8:
package com.java8; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; /** * source : crtr4u.com * Author : Swapnil V */ public class PredicateDemo2 { public static void main(String[] args) { Predicate<Integer> isEvenNumber = num -> num % 2 == 0; List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6); List<Integer> evenNumbers = numbers.stream() .filter(isEvenNumber) .collect(Collectors.toList()); System.out.println(" Even Numbers "+evenNumbers); } }
Output :
Even Numbers [2, 4, 6]
2.Customizing Filtering Logic :
package com.java8; import java.util.function.Predicate; /** * source : crtr4u.com * Author : Swapnil V */ public class PredicateDemo3 { public static void main(String[] args) { Predicate<String> startsWithAIgnoreCase = str -> str.toUpperCase().startsWith("A"); Predicate<String> endsWithBIgnoreCase = str -> str.toLowerCase().endsWith("b"); // Combining predicates using logical operators: Predicate<String> startsWithAAndEndsWithB = startsWithAIgnoreCase.and(endsWithBIgnoreCase); System.out.println(startsWithAAndEndsWithB.test("AB")); System.out.println(startsWithAAndEndsWithB.test("ABC")); System.out.println(startsWithAAndEndsWithB.test("AdfvCb")); } }
Output :
true false true
Additional Features:
- Combining Predicates:
and()
: Combines two predicates with a logical AND.or()
: Combines two predicates with a logical OR.negate()
: Negates a predicate.- Default Methods:
isEqual()
: Returns a predicate that tests if two arguments are equal.
By understanding and effectively using Predicates, you can write more concise, expressive, and functional-style Java code.
package com.java8; import java.util.function.Predicate; /** * source : crtr4u.com * Author : Swapnil V */ public class PredicateDemo3 { public static void main(String[] args) { Predicate<Integer> isEqual10 = Predicate.isEqual(10); System.out.println(isEqual10.test(10)); //true } }
Combining Predicates:
One of the powerful aspects of Predicates is their ability to be combined using logical operators to create more complex filtering conditions.
Predicate<Integer> isEven = num -> num % 2 == 0; Predicate<Integer> isGreaterThanFive = num -> num > 5; // Combining using AND: Predicate<Integer> isEvenAndGreaterThanFive = isEven.and(isGreaterThanFive); // Combining using OR: Predicate<Integer> isEvenOrGreaterThanFive = isEven.or(isGreaterThanFive); // Negating a Predicate: Predicate<Integer> isNotEven = isEven.negate();
Using Predicates with Streams:
Predicates are frequently used with Java Streams to filter elements based on specific criteria:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8); // Filter even numbers greater than 5 List<Integer> filteredNumbers = numbers.stream() .filter(isEvenAndGreaterThanFive) .collect(Collectors.toList());
Method References with Predicates:
Method references can be used to concisely create Predicates:
Predicate<String> isNull = Objects::isNull; Predicate<String> isNotEmpty = String::isEmpty.negate();
Real-world Example: Filtering a List of Products
List<Product> products = ... // A list of products with price and category // Filter products that are electronics and cost more than $100 Predicate<Product> isElectronic = product -> product.getCategory().equals("Electronics"); Predicate<Product> costsMoreThan100 = product -> product.getPrice() > 100; List<Product> filteredProducts = products.stream() .filter(isElectronic.and(costsMoreThan100)) .collect(Collectors.toList());
Key Benefits of Predicates:
- Functional Programming Style: Encourages a more functional approach to problem-solving.
- Concise and Expressive: Lambda expressions and method references make code more readable.
- Reusability: Predicates can be reused in different parts of your code.
- Flexibility: Combining and negating predicates allows for complex filtering scenarios.
- Integration with Streams: Seamlessly integrates with Java Streams for powerful data processing.
Using Predicates with Collectors:
Predicates can be used with Collectors to group and partition elements based on specific criteria.
package com.java8; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.function.Predicate; import java.util.stream.Collectors; /** * source : crtr4u.com * Author : Swapnil V */ public class PredicateDemo3 { public static void main(String[] args) { Predicate<Integer> isEvenPredicate=I->I%2==0; List<Integer> numberList=Arrays.asList(1,4,6,8,3); Map<Boolean, List<Integer>> partitionedNumbers =numberList.stream() .collect(Collectors.partitioningBy(isEvenPredicate)); System.out.println(partitionedNumbers); } }
Output :
{false=[1, 3], true=[4, 6, 8]}
Real-world Example of Predicate : Filtering a List of Employees
List<Employee> employees = ... // A list of employees with name, age, and department // Filter employees who are older than 30 and work in the IT department Predicate<Employee> isOlderThan30 = employee -> employee.getAge() > 30; Predicate<Employee> isInTheITDepartment = employee -> employee.getDepartment().equals("IT"); List<Employee> filteredEmployees = employees.stream() .filter(isOlderThan30.and(isInTheITDepartment)) .collect(Collectors.toList());
Key Considerations:
- Performance: While Predicates provide a concise and expressive way to filter data, it’s important to consider performance implications, especially when dealing with large datasets.
- Readability: Use clear and concise lambda expressions to improve code readability.
- Testing: Write unit tests to ensure the correctness of your Predicate implementations.
Top 10 Java Predicate Interview Questions and Answers
Here are 10 common Java Predicate interview questions, along with concise and informative answers:
1. What is a Predicate in Java 8?
A Predicate is a functional interface that represents a boolean-valued function of one argument. It’s used to filter elements based on a specific condition.
2. How do you create a Predicate using a lambda expression?
Predicate<Integer> isEven = num -> num % 2 == 0;
3. How can you combine multiple Predicates?
You can combine Predicates using logical operators like and()
, or()
, and negate()
:
Predicate<Integer> isPositive = num -> num > 0; Predicate<Integer> isDivisibleBy3 = num -> num % 3 == 0; Predicate<Integer> isPositiveAndDivisibleBy3 = isPositive.and(isDivisibleBy3);
4. How do you use Predicates with Java Streams?
You can use filter()
to filter elements based on a Predicate:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6); List<Integer> evenNumbers = numbers.stream() .filter(isEven) .collect(Collectors.toList());
5. Explain the concept of method references with Predicates.
Method references can be used to concisely create Predicates:
Predicate<String> isNull = Objects::isNull;
6. How can you use Predicates to partition a collection?
You can use partitioningBy
collector with a Predicate to divide a collection into two groups:
Map<Boolean, List<Integer>> partitionedNumbers = numbers.stream() .collect(Collectors.partitioningBy(isEven);
7. What are the performance implications of using Predicates?
While Predicates offer a concise and expressive way to filter data, excessive use can impact performance, especially with large datasets. It’s important to consider the complexity of the Predicate and the size of the collection.
8. How can you improve the readability of Predicate expressions?
- Use clear and concise lambda expressions.
- Break down complex Predicates into smaller, reusable ones.
- Use meaningful variable names.
9. What are some common use cases for Predicates?
- Filtering collections
- Validating input data
- Searching for specific elements
- Grouping and partitioning data
10. Can you give a real-world example of using Predicates?
Consider a scenario where you have a list of products and you want to filter products that are electronics and cost more than $100:
Predicate<Product> isElectronic = product -> product.getCategory().equals("Electronics"); Predicate<Product> costsMoreThan100 = product -> product.getPrice() > 100; List<Product> filteredProducts = products.stream() .filter(isElectronic.and(costsMoreThan100)) .collect(Collectors.toList());
Remember to practice these concepts and apply them in real-world scenarios to gain a deeper understanding of Predicates in Java 8.
Happy Learning…