Predicate in Java

I'm assuming you're talking about com.google.common.base.Predicate<T> from Guava.

From the API:

Determines a true or false value for a given input. For example, a RegexPredicate might implement Predicate<String>, and return true for any string that matches its given regular expression.

This is essentially an OOP abstraction for a boolean test.

For example, you may have a helper method like this:

static boolean isEven(int num) {
   return (num % 2) == 0; // simple
}

Now, given a List<Integer>, you can process only the even numbers like this:

    List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    for (int number : numbers) {
        if (isEven(number)) {
            process(number);
        }
    }

With Predicate, the if test is abstracted out as a type. This allows it to interoperate with the rest of the API, such as Iterables, which have many utility methods that takes Predicate.

Thus, you can now write something like this:

    Predicate<Integer> isEven = new Predicate<Integer>() {
        @Override public boolean apply(Integer number) {
            return (number % 2) == 0;
        }               
    };
    Iterable<Integer> evenNumbers = Iterables.filter(numbers, isEven);

    for (int number : evenNumbers) {
        process(number);
    }

Note that now the for-each loop is much simpler without the if test. We've reached a higher level of abtraction by defining Iterable<Integer> evenNumbers, by filter-ing using a Predicate.

API links

  • Iterables.filter
    • Returns the elements that satisfy a predicate.

On higher-order function

Predicate allows Iterables.filter to serve as what is called a higher-order function. On its own, this offers many advantages. Take the List<Integer> numbers example above. Suppose we want to test if all numbers are positive. We can write something like this:

static boolean isAllPositive(Iterable<Integer> numbers) {
    for (Integer number : numbers) {
        if (number < 0) {
            return false;
        }
    }
    return true;
}

//...
if (isAllPositive(numbers)) {
    System.out.println("Yep!");
}

With a Predicate, and interoperating with the rest of the libraries, we can instead write this:

Predicate<Integer> isPositive = new Predicate<Integer>() {
    @Override public boolean apply(Integer number) {
        return number > 0;
    }       
};

//...
if (Iterables.all(numbers, isPositive)) {
    System.out.println("Yep!");
}

Hopefully you can now see the value in higher abstractions for routines like "filter all elements by the given predicate", "check if all elements satisfy the given predicate", etc make for better code.

Unfortunately Java doesn't have first-class methods: you can't pass methods around to Iterables.filter and Iterables.all. You can, of course, pass around objects in Java. Thus, the Predicate type is defined, and you pass objects implementing this interface instead.

See also

  • Wikipedia/Higher-order function
  • Wikipedia/Filter (higher-order function)

A predicate is a function that returns a true/false (i.e. boolean) value, as opposed to a proposition which is a true/false (i.e. boolean) value. In Java, one cannot have standalone functions, and so one creates a predicate by creating an interface for an object that represents a predicate and then one provides a class that implements that interface. An example of an interface for a predicate might be:

public interface Predicate<ARGTYPE>
{
    public boolean evaluate(ARGTYPE arg);
}

And then you might have an implementation such as:

public class Tautology<E> implements Predicate<E>
{
     public boolean evaluate(E arg){
         return true;
     }
}

To get a better conceptual understanding, you might want to read about first-order logic.

Edit
There is a standard Predicate interface (java.util.function.Predicate) defined in the Java API as of Java 8. Prior to Java 8, you may find it convenient to reuse the com.google.common.base.Predicate interface from Guava.

Also, note that as of Java 8, it is much simpler to write predicates by using lambdas. For example, in Java 8 and higher, one can pass p -> true to a function instead of defining a named Tautology subclass like the above.