Java 8 Predicates with example

Like many other functional interfaces in Java 8, Java introduces a functional interface called Java Predicates. A functional interface is one that contains only one abstract method, for details read functional interface. Predicate represent (Boolean-valued function) which takes the only argument. It returns true if the input argument matches the predicate or false.

@FunctionalInterface
java.util.function. public interface Predicate

Functional Method:

boolean test(T t);

Evaluates this predicate on the given argument and return true if the input argument matches the predicate, otherwise false.

Default methods:

default Predicate and(Predicate other)

Returns a composed predicate that represents a short-circuiting logical AND of this predicate and another. When evaluating the composed predicate, if this predicate is false, then the other predicate is not evaluated.

Any exceptions thrown during evaluation of either predicate are relayed to the caller; if the evaluation of this predicate throws an exception, the other predicate will not be evaluated.

default Predicate or(Predicate other)

Returns a composed predicate that represents a short-circuiting logical OR of this predicate and another. When evaluating the composed predicate, if this predicate is true, then the other predicate is not evaluated.

Any exceptions thrown during evaluation of either predicate are relayed to the caller; if the evaluation of this predicate throws an exception, the other predicate will not be evaluated.

default Predicate negate()

Returns a predicate that represents the logical negation of this predicate.

Static method:

static Predicate isEqual(Object targetRef)

Returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object).

Example: Predicate to check empty string

import java.util.function.Predicate;

public class PredicateExample {

	 //predicate to check if a String is empty 
	static Predicate<String> isEmpty = new Predicate<String>() {
		
		@Override
		public boolean test(String t) {
			
			return (t == null || t.trim().isEmpty());
		}
	};  

	public static void main(String[] args) {
		
		System.out.println("Empty "+isEmpty.test("Java"));
		System.out.println("Empty "+isEmpty.test("Java "));
		System.out.println("Empty "+isEmpty.test(""));
		System.out.println("Empty "+isEmpty.test(" "));
		System.out.println("Empty "+isEmpty.test(null));
		
	}
}

The output will be:

Empty false
Empty false
Empty true
Empty true
Empty true

The isEmpty() predicate mentioned above can also be written as below using a lambda expression.

static Predicate<String> isEmptyString = s ->  (s == null || s.trim().isEmpty()); 

Let’s see a few more Predicate examples using its other methods.

and():

import java.util.function.Predicate;

public class PredicateExample {

	static Predicate<Integer> greaterThanZero = i -> i  > 0;
	
	static Predicate<Integer> lessThanHundred = i -> i  < 100;
	
	static Predicate<Integer> andPridicate = greaterThanZero.and(lessThanHundred);

	
	public static void main(String[] args) {
		System.out.println("Result "+andPridicate.test(10));
		System.out.println("Result "+andPridicate.test(99));
		System.out.println("Result "+andPridicate.test(101));
		System.out.println("Result "+andPridicate.test(-1));
	}
}

The output will be:

Result true
Result true
Result false
Result false

or() and negate() method: To see the uses of or () and negate() methods observe the below code snippet.

Let’s create a class named Employee.

public class Employee {

	private int empId;

	private String name;

	private String department;

	private int age;

	public Employee() {

	}

	public Employee(int empId, String name, String department, int age) {
		super();
		this.empId = empId;
		this.name = name;
		this.department = department;
		this.age = age;
	}

	public int getEmpId() {
		return empId;
	}

	public void setEmpId(int empId) {
		this.empId = empId;
	}

	public String getName() {
		return name;
	}

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

	public String getDepartment() {
		return department;
	}

	public void setDepartment(String department) {
		this.department = department;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Employee [empId=" + empId + ", name=" + name + ", department=" + department + ", age=" + age + "]";
	}

}

Create another class to define predicates, in this class will define two predicates to filter the employees by age and by the department.

import java.util.function.Predicate;

public class EmployeePredicates {

	public static Predicate<Employee> ageAbove25(){
		return employee -> employee.getAge() >= 25;
	}
	
	public static Predicate<Employee> ofDepartent(String dept){
		return emp -> emp.getDepartment().equalsIgnoreCase(dept);
	}

}

Now let’s create a class to run the test for the above-mentioned predicates.

import java.util.Arrays;
import java.util.List;

public class PredicateExample {

public static void main(String[] args) {
		
		List<Employee> employees = createEmpData();
		
		// using negate ()
		// It return a logical negation of the predicate 
		System.out.println("negate start");
		employees.stream().filter(EmployeePredicates.ageAbove25().negate()).forEach(System.out::println);
		System.out.println("negate end");
		
		// using or ()
		// It returns a composed predicate that represents a short-circuiting logical
		// OR of this predicate and another.
		System.out.println("or start");
		employees.stream().filter(EmployeePredicates.ageAbove25()
				.or(EmployeePredicates.ofDepartent("Finance"))).forEach(System.out::println);
		System.out.println("or end");
			
	}
	
	static List<Employee> createEmpData(){
		return Arrays.asList(new Employee [] {
				new Employee(1001, "Tom", "IT", 26),
				new Employee(1002, "Ram", "IT", 28),
				new Employee(1003, "Shyam", "Finance", 21),
				new Employee(1003, "Jamal", "Finance", 23),
				new Employee(1004, "Aman", "Finance", 29),
				new Employee(2002, "Raghu", "Finance", 30),
				new Employee(2005, "john", "HR", 24),
				new Employee(3001, "Foo", "Test", 20),
				new Employee(3007, "bar", "Test", 23),
		});
	}

}

Output:

negate start
Employee [empId=1003, name=Shyam, department=Finance, age=21]
Employee [empId=1003, name=Jamal, department=Finance, age=23]
Employee [empId=2005, name=john, department=HR, age=24]
Employee [empId=3001, name=Foo, department=Test, age=20]
Employee [empId=3007, name=bar, department=Test, age=23]
negate end

or start
Employee [empId=1001, name=Tom, department=IT, age=26]
Employee [empId=1002, name=Ram, department=IT, age=28]
Employee [empId=1003, name=Shyam, department=Finance, age=21]
Employee [empId=1003, name=Jamal, department=Finance, age=23]
Employee [empId=1004, name=Aman, department=Finance, age=29]
Employee [empId=2002, name=Raghu, department=Finance, age=30]
or end

As described above the negate method will perform logical negation of the predicate hence returned all the employees having age less than 25.

Similarly, the or method will return a composed predicate that represents a logical OR between the given two predicates.

Reference:
Java Doc Predicate

Read about Java 8 forEach() method.

Happy Learning !!

Leave a Comment