Introduction
Predicate is Functional Interface which will useful to return true or false.We can use the Predicate with Stream filter() method for filtering elements of steam.
Case Studies:
For examples if we can to get the list of employees whose name starts with letter j and age is greater than 35 and experience with 5 years minimum.
Predict holds the lambda function where Predict will be reusable in the program or in the class.
Inline predicate object
List<Employee> empList= Employee.getEmpList(); // we created a Predict where employee first name starts with j and emp id is greater than e Predicate<Employee> whoseNameContainsJ= emp -> emp.fname.startsWith("j") && emp.empId>=2; // now we can pass this Predict to filter method of Stream List<Employee> empList_starts_with_j= empList.stream().filter(whoseNameContainsJ).collect(Collectors.toList()); Consumer<Employee> action= (emp) -> { System.out.println(emp.fname+" with the Emp id:"+ emp.empId); }; //empList_starts_with_j.forEach(action); Predicate<Employee> namePredictJ= emp->emp.fname.startsWith("j"); Predicate<Employee> idgreaterThan2= emp->emp.empId>=2; Comparator<Employee> sortByFname= Comparator.comparing(Employee::getFname); List<Employee> empListWithJandID2= empList.stream().filter(namePredictJ.or(idgreaterThan2)).sorted(sortByFname).collect(Collectors.toList()); empListWithJandID2.forEach(action);In the above code at line 4 we have created an inline Predicate object by assighning lambda function as a value
Implementing predicate as a separate class
In the above example we have written predicate as inline statement, but if we want to use that in another class we need to implement a predicate class as a separate class as shown in the following example. We must create a class which implements Predicate interface by overriding test() method where we can write the logic for predicate.public class MarksPredicate implements Predicate<StudentMarks> { @Override public boolean test(StudentMarks t) { // TODO Auto-generated method stub boolean pass = (t.totalMarks > 200) ? true : false; return pass; } }In the above code we have implemented a method test() which returns true or false.
public class StudentMarks { int totalMarks; String htno; String name; char gender; public StudentMarks(int totalMarks, String htno, String name, char gender) { super(); this.totalMarks = totalMarks; this.htno = htno; this.name = name; this.gender = gender; } public int getTotalMarks() { return totalMarks; } public void setTotalMarks(int totalMarks) { this.totalMarks = totalMarks; } public String getHtno() { return htno; } public void setHtno(String htno) { this.htno = htno; } public String getName() { return name; } public void setName(String name) { this.name = name; } public char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } }
public class StudentsInfo { public static void main(String[] args) { StudentMarks sm1 = new StudentMarks(250, "R001", "Sachin", 'M'); StudentMarks sm2 = new StudentMarks(150, "R002", "Ganguly", 'M'); StudentMarks sm3 = new StudentMarks(350, "R003", "Mithali Raj", 'F'); StudentMarks sm4 = new StudentMarks(550, "R004", "Rojanitha", 'F'); List<StudentMarks> lsm = new ArrayList<StudentMarks>(); lsm.add(sm1); lsm.add(sm2); lsm.add(sm3); lsm.add(sm4); // get list of students who passed Predicate<StudentMarks> p = new MarksPredicate(); List<StudentMarks> passed_students_list = lsm.stream(). filter(p). collect(Collectors.toList()); System.out.println("List of students who got pass marks \n*************************************"); passed_students_list.forEach(psl -> { System.out.println(psl.getHtno() + " : " + psl.getName() + " : " + psl.getTotalMarks() + " : " + (psl.getGender() == 'M' ? "Male" : "Female")); }); } } /* Output List of students who got pass marks ************************************* R001 : Sachin : 250 : Male R003 : Mithali Raj : 350 : Female R004 : Rojanitha : 550 : Female */In the above code in line 17 we have created a Predicate object by MarksPredicate class which is an implementation class of Predicate interface
Predicate as a method return type
We can create a predicate from method too by taking Predicate as methor return type.public class PredicatesMarks { // Following method returns Predicate to get only female students public Predicate<StudentMarks> onlyFemale() { Predicate<StudentMarks> of = si -> si.gender == 'F'; return of; // in a single line we can write the above code as bellow // return si -> si.gender == 'F'; } }In the above code at the line 4 the method onlyFemale() has a Predicate as a Return type where StudnetMarks is a POJO class for studnet marks.
public class StudentsInfo { public static void main(String[] args) { StudentMarks sm1 = new StudentMarks(250, "R001", "Sachin", 'M'); StudentMarks sm2 = new StudentMarks(150, "R002", "Ganguly", 'M'); StudentMarks sm3 = new StudentMarks(350, "R003", "Mithali Raj", 'F'); StudentMarks sm4 = new StudentMarks(550, "R004", "Rojanitha", 'F'); List<StudentMarks> lsm = new ArrayList<StudentMarks>(); lsm.add(sm1); lsm.add(sm2); lsm.add(sm3); lsm.add(sm4); PredicatesMarks pm = new PredicatesMarks(); // in the next line the method onlyFemale() returns a Predicate Predicate<StudentMarks> predicateFemale = pm.onlyFemale(); List<StudentMarks> onlyFemaleStudnetsList = lsm.stream().filter(predicateFemale).collect(Collectors.toList()); System.out.println("\nList of Feamle Students \n******************************"); onlyFemaleStudnetsList.forEach(fs -> { System.out.println(fs.getHtno() + " : " + fs.getName() + " : " + fs.getTotalMarks() + " : " + (fs.getGender() == 'M' ? "Male" : "Female")); }); } }In the above code at the line 18we have created a Predicate object by invoking a method onlyFemale() which has a Prediacte as a return type in a class PredicatesMarks.java
Filtering with two predicates same time with and() method
In previous examples of code we have found list of students who got pass marks separately and list of female students separately by applying filtering with Predicates. If we want to find only list of female students who passed, then we need to apply two predicates at a same time, for this purpose we are using and() method of Predicate, to apply predicates as a chain with and() method and or() method( will be discussed in next section)public class StudentsInfo { public static void main(String[] args) { StudentMarks sm1 = new StudentMarks(250, "R001", "Sachin", 'M'); StudentMarks sm2 = new StudentMarks(150, "R002", "Ganguly", 'M'); StudentMarks sm3 = new StudentMarks(350, "R003", "Mithali Raj", 'F'); StudentMarks sm4 = new StudentMarks(550, "R004", "Rojanitha", 'F'); List<StudentMarks> lsm = new ArrayList<StudentMarks>(); lsm.add(sm1); lsm.add(sm2); lsm.add(sm3); lsm.add(sm4); PredicatesMarks pm = new PredicatesMarks(); // in the next line the method onlyFemale() returns a Predicate Predicate<StudentMarks> predicateFemale = pm.onlyFemale(); // get list of students who passed and gender is female Predicate<StudentMarks> p = new MarksPredicate(); List<StudentMarks> ppp = lsm.stream() .filter(p.and(predicateFemale)) .collect(Collectors.toList()); System.out.println("\nList of FEMLAE students who got pass marks \n*************************************"); ppp.forEach(psl -> { System.out.println(psl.getHtno() + " : " + psl.getName() + " : " + psl.getTotalMarks() + " : Female"); }); } } // Output /* List of FEMLAE students who got pass marks ************************************* R003 : Mithali Raj : 350 : Female R004 : Rojanitha : 550 : Female */In the highlighted block of the above code you can notice that we have used and() method of Predicate to apply another Filtering with another Predicate.
Two predicates chaining with or() method
PredicatesMarks pm= new PredicatesMarks(); // in the next line the method onlyFemale() returns a Predicate Predicate<StudentMarks> predicateFemale= pm.onlyFemale(); // In line Predicate for name start with letter s Predicate<StudentMarks> nameStartsWithS= stu -> stu.getName().startsWith("S"); List<StudentMarks> onlyFemaleStudnetsList=lsm.stream().filter(predicateFemale.or(nameStartsWithS)).collect(Collectors.toList()); System.out.println("\nList of Feamle Students or name started with Letter of any gender\n****************************************"); onlyFemaleStudnetsList.forEach( fs -> { System.out.println(fs.getHtno() + " : " + fs.getName() + " : " + fs.getTotalMarks() + " : " + (fs.getGender() == 'M' ? "Male" : "Female")); }); //output /* List of Feamle Students or name started with Letter of any gender **************************************** R001 : Sachin : 250 : Male R003 : Mithali Raj : 350 : Female R004 : Rojanitha : 550 : Female */
Reverse filter with Predicate.negate() method
We have a predicate for getting only female, now we can use this same predicate to get male students by using negate() method of PredicatePredicatesMarks pm= new PredicatesMarks(); // in the next line the method onlyFemale() returns a Predicate Predicate<StudentMarks> predicateFemale= pm.onlyFemale(); // In line Predicate for name start with letter s Predicate<StudentMarks> nameStartsWithS= stu -> stu.getName().startsWith("S"); List<StudentMarks> onlyFemaleStudnetsList=lsm.stream().filter(predicateFemale.negate()).collect(Collectors.toList()); System.out.println("\nList of male students\n****************************************"); onlyFemaleStudnetsList.forEach( fs -> { System.out.println(fs.getHtno() + " : " + fs.getName() + " : " + fs.getTotalMarks() + " : " + (fs.getGender() == 'M' ? "Male" : "Female")); }); //output /* List of Male Students **************************************** R001 : Sachin : 250 : Male R002 : Ganguly : 150 : Male */
Post a Comment
Post a Comment