SEARCH BY

All

  • All
  • Java8
  • Spring

java8 Predicate for filtering Stream effectively

Post a Comment

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 Predicate
		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.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
*/
        
jaya
I love software designing, coding, writing and teaching...

Share this article

Related Posts

Post a Comment

Place your code in <em> </em> tags to send in comments | Do not add hyper links in commnet

Close

Subscribe our newsletter for the latest articles directly into your email inbox