How to fetch items of a list matching some condition in java / How to partition an Object list based on some field value in java

Suppose I have a list of custom objects, say Employee. The Employee class has two fields namely name (name of employee) and isExEmployee (Boolean value indicating that the employee is an ex-employee) as below:

public class Employee {
	private String name;
	private boolean isExEmployee;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public boolean isExEmployee() {
		return isExEmployee;
	}

	public void setExEmployee(boolean isExEmployee) {
		this.isExEmployee = isExEmployee;
	}
}

Now I have a list which contains many employees, some of which are ex-employee and I want the name of those ex-employees. How would I do that?
One way is to iterate the whole list and check the value of isExEmployee and add all ex-employees to a sub-list like:

List exEmployeeList = new ArrayList<>();
for(Employee e : employeeList) {
	if(e.isExEmployee){
		exEmployeeList.add(e);
	}
}

This is the traditional and most used way. Let’s do it a newer and java 8 way:

List exEmployeeList = employeeList.stream().filter((p) -> p.isExEmployee()).collect(Collectors.toList());

This will give you the list of all ex-employees. Cool !!! isn’t it.
For those who wish to understand what’s happening here, read on….

  1. First we call stream() on list object. stream() is a new method added to Collection class in java 8 as:
    employeeList.stream(); (1)
    This returns a stream of elements of the supplied Collection (list in this case). On this stream we call filter method. filter() method is declared in Stream interface and accepts a Predicate as:
    employeeList.stream.filter(Predicate<? super T> predicate) (2)
    Predicate is again an interface added in java 8 and represents a condition on which to filter the list. Predicate interface has only method (with the name, test) as:
    boolean test(T t)
    Now what we pass to the filter method may be somewhat weird:
    p->p.isExEmployee()
    This is a Lamba expression again added in java 8 and matches the signature of test method of Predicate interface whose object is expected by the filter method of Stream interface in (2) above. Let’s see how this Lambda expression is evaluated:
    test method of Predicate interface has a return type of boolean and so is the return type of p.isExEmployee(). test method accepts single argument which matches the count of left side parameters in expression: p->p.isExEmployee().
    Next, the collect method collects all objects matching the given criteria
    employeeList.stream().filter((p) -> p.isExEmployee()).collect(Collectors.toList());
    In the above statement the collect method collects all elements for which isExEmployee() returns true and transforms them into a list.

Let’s tweak in:

1. Stream in Collections is different from input and output streams in java IO.
2. Stream may be sequential or parallel in which case it is capable of being operated by multiple threads.
3. The character p in Lambda expression has no significance. Any character or sequence of characters can be used in its place provided that characters on both sides are the same . em->em.isExEmployee() is also valid.
4. In other words, the lambda expression in above example, implements the test() method of Predicate interface.

Leave a Reply