1. Overview
In this tutorial, We'll learn how to work and use the Predicate Functional Interface.
In the previous post, We have discussed "Introduction to Functional Interfaces in Java 8". Explained an easy manner to understand the type of Functional Interfaces.
Predicate Functional interface is part of java.lang.function package.
Predicate is one of the categories of Function Interfaces (Suppliers, Consumer, Predicates and Function)
Below is the definition from Predicate API.
@FunctionalInterface public interface Predicate<T>
Predicate has an abstract method named test(T t) which takes only one argument and does return a boolean value such as true or false.
This is mainly used to test a condition to perform certain operations.
test(T t) method can be called as Functional Method. Below is the signature.
boolean test(T t)
Predicate has many non-abstract methods apart from test(). Those are two static and three default methods.
Static Methods:
static <T> Predicate<T> isEqual(Object targetRef) static <T> Predicatenot(Predicate target)
Default Methods:
default Predicateand(Predicate other) default Predicate<T> negate() default Predicate<T> or(Predicate other)
We will be discussing all these methods with examples.
In all examples, We will be using the below Student class.
class Student { int id; String name; int age; public Student(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; } @Override public boolean equals(Object obj) { Student other = (Student) obj; if (age != other.age) return false; if (id != other.id) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
2. Predicate test(T t)
This is the function method in the Predicate interface.2.1 Example 1
This is a simple straight forward example to creating a predicate for student age to check for more than 18 years.PredicateagePredicate = s -> s.getAge() > 18; Student s1 = new Student(100, "Larry", 25); boolean is18Plus = agePredicate.test(s1); if(is18Plus) { System.out.println("Larray is 18 plus"); }
Output:
Lary is 18 plus
2.2 Example with List stream
Creating a list of Students.ListstuList = new ArrayList<>(); stuList.add(new Student(100, "Lary", 10)); stuList.add(new Student(200, "page", 20)); stuList.add(new Student(101, "sundar", 30)); stuList.add(new Student(202, "pichai", 17));
Converting a list to stream and passing a Predicate to filter method.
Listlist18Plus = stuList.stream().filter(stu -> stu.getAge() > 18).collect(Collectors.toList()); System.out.println(list18Plus);
Now, This filter will be executed for every student in the stuList and checks the predicate condition. If the condition returns true then collect into List.
Output:
This produces the output with 18+ age students.
[Student [id=100, name=page, age=20], Student [id=100, name=sundar, age=30]]
3. The Predicate and(Predicate p) method
Predicate can be used in chaining. That means we can call and method on existing Predicate instance.
Now, We want to add an additional test condition to the existing predicate that name starts with "p".
and() method is used to club two predicates and produces a boolean result. It returns two if and only if two predicate's are matched, Otherwise false.
This is similar to the logical AND and as below.
predicate1.and(prediate2);
3.1 Example 1
Existing predicate:PredicateagePredicate = s -> s.getAge() > 18;
New Predicate:
PredicatenamePredicate = s -> s.getName().startsWith("p"); Predicate ageNamePredicate = agePredicate.and(namePredicate); Student page = new Student(200, "page", 20); boolean isMatched = ageNamePredicate.test(page); System.out.println(isMatched);
Output:
true
3.2 Example With Streams
ListandResult = stuList.stream().filter(ageNamePredicate).collect(Collectors.toList()); System.out.println(andResult);
Output:
This produces only one student because there is only one Student with age > 18 and the name starts with "p".
[Student [id=200, name=page, age=20]]
4 Predicate or(Predicate p) method
or(Predicate p) method works the same as logical OR. This method takes another predicate as an argument and returns a boolean value.
Note: This or() method is called on another predicate.
predicate1.or(prediate2);
If anyone of the Predicate's is true then predicate returns true.
See the example with collections and streams.
Creating or() predicate.
Passing orPredicate to Stream filter() method.
Output:
isEqual() method takes Object as an argument. That means we can pass any object to this. This internally calls Objects equals() method.
In this example, we have overridden the equals() method Student class.
isEqual is a static method. So, it can be called directly invoked on Predicate. See the below example.
Creating a student object.
Creating a predicate with isEqual() method and passing sunder obj to it.
Now passing this predicate to Stream filter() method and checks.
6. default Predicate
negate() returns a Predicate that does not satisfy the condition.
Let us write an example program to understand the negate() default method.
Output:
First, write the predicate to find the student name starts with 'p'
Next, invoked the negate() on it and returned a new predicate.
Finally, Passed negate to the filter method and then collected the students whose names not started with 'p'. Observe the above output.
not() method is newly introduced as part of Java 11 API. This works similarly to the negate() method but it does take the Predicate as an argument.
And also this is a static method so we can access the class name directly. not() method uses the target.negate() method internally.
Now it time to an example program on not() function.
Output:
We should be knowing while using Predicate methods such as and(..), isEqual(..), or(..) and not(..) take a predicate as arguments. If we pass null then it will throw Runtime NullPointerException.
ArrayList API has a method removeif().
Removes all of the elements of this collection that satisfy the given predicate. Errors or runtime exceptions thrown during the iteration or by the predicate are relayed to the caller.
This returns boolean, true - if any elements removed. false - otherwise.
Output:
In this detailed post, We've seen what is Predicate Functional Interface and its methods.
Example of each method and how to use them.
The Predicate is widely used in Java 8 Stream api and should be used with Lambda Expressions.
And also saw the removeIf() method in the ArrayList API that uses Predicate.
All the code shown in this post is over GitHub.
See the example with collections and streams.
Creating or() predicate.
PredicateorPredicate = agePredicate.or(namePredicate);
Passing orPredicate to Stream filter() method.
ListorResult = stuList.stream().filter(orPredicate).collect(Collectors.toList()); System.out.println(orResult);
Output:
[Student [id=200, name=page, age=20], Student [id=101, name=sundar, age=30], Student [id=202, name=pichai, age=17]]
5. Predicate isEqual(Object obj)
isEqual() method takes Object as an argument. That means we can pass any object to this. This internally calls Objects equals() method.
In this example, we have overridden the equals() method Student class.
isEqual is a static method. So, it can be called directly invoked on Predicate. See the below example.
Creating a student object.
Student sunder = new Student(200, "page", 20);
Creating a predicate with isEqual() method and passing sunder obj to it.
PredicateisEqualPredicate = Predicate.isEqual(page);
Now passing this predicate to Stream filter() method and checks.
ListisEqualResult = stuList.stream().filter(isEqualPredicate).collect(Collectors.toList()); System.out.println(isEqualResult);
Output:
[Student [id=200, name=page, age=20]]
6. default Predicate negate()
negate() returns a Predicate that does not satisfy the condition.
Let us write an example program to understand the negate() default method.
PredicatenamePredicate = s -> s.getName().startsWith("p"); Predicate nameNegatePredicate = namePredicate.negate(); List negateResult = stuList.stream().filter(nameNegatePredicate).collect(Collectors.toList()); System.out.println(negateResult);
Output:
[Student [id=100, name=Lary, age=10], Student [id=101, name=sundar, age=30]]
First, write the predicate to find the student name starts with 'p'
Next, invoked the negate() on it and returned a new predicate.
Finally, Passed negate to the filter method and then collected the students whose names not started with 'p'. Observe the above output.
7. Predicate not(Predicate target)
not() method is newly introduced as part of Java 11 API. This works similarly to the negate() method but it does take the Predicate as an argument.
And also this is a static method so we can access the class name directly. not() method uses the target.negate() method internally.
Now it time to an example program on not() function.
PredicateagePredicate = s -> s.getAge() > 18; Predicate ageNegatePredicate = Predicate.not(agePredicate); List notResult = stuList.stream().filter(ageNegatePredicate).collect(Collectors.toList()); System.out.println(notResult);
Output:
[Student [id=100, name=Lary, age=10], Student [id=202, name=pichai, age=17]]
8. NullPointerException
We should be knowing while using Predicate methods such as and(..), isEqual(..), or(..) and not(..) take a predicate as arguments. If we pass null then it will throw Runtime NullPointerException.
9. ArrayList.removeif(Predicate p)
ArrayList API has a method removeif().
Removes all of the elements of this collection that satisfy the given predicate. Errors or runtime exceptions thrown during the iteration or by the predicate are relayed to the caller.
public boolean removeIf(Predicate filter)
This returns boolean, true - if any elements removed. false - otherwise.
Example:
System.out.println("Student list size before removal : "+stuList.size()); boolean removed = stuList.removeIf( s -> s.getId() == 100); System.out.println(removed); System.out.println("Student list size after removal : "+stuList.size());
Output:
Student list size before removal : 4 true Student list size after removal : 3
10. Conclusion
In this detailed post, We've seen what is Predicate Functional Interface and its methods.
Example of each method and how to use them.
The Predicate is widely used in Java 8 Stream api and should be used with Lambda Expressions.
And also saw the removeIf() method in the ArrayList API that uses Predicate.
All the code shown in this post is over GitHub.
No comments:
Post a Comment
Please do not add any spam links in the comments section.