Java Predicate

Java Predicate tutorial shows how to use predicates in Java. With predicates, we can create code that is more clean and readable. Predicates also help to create better tests.

Predicate

Predicate in general meaning is a statement about something that is either true or false. In programming, predicates represent single argument functions that return a boolean value.

Java Predicate

Predicates in Java are implemented with interfaces. Predicate<T> is a generic functional interface representing a single argument function that returns a boolean value. It is located in the java.util.function package. It contains a test(T t) method that evaluates the predicate on the given argument.

In Java we do not have standalone functions. Furthermore, methods are not first-class citizens. (They cannot be added to collections or passed to methods as parameters.) Therefore, we define interfaces and create objects from these interfaces. Such objects can be then passed to methods such as Iterables.filter(). With Java lambdas it is much easier to work with predicates.

Java Predicate example

The following example creates a simple Java Predicate.

JavaPredicateEx.java
package com.zetcode;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

class BiggerThanFive<E> implements Predicate<Integer> {

    @Override
    public boolean test(Integer v) {
        
        Integer five = 5;
        
        return v > five;
    }
}

public class JavaPredicateEx {

    public static void main(String[] args) {

        List<Integer> nums = Arrays.asList(2, 3, 1, 5, 6, 7, 8, 9, 12);
        
        BiggerThanFive btf = new BiggerThanFive();
        
        nums.stream().filter(btf).forEach(System.out::println);
    }
}

In the example, the predicate is used to filter integers.

class BiggerThanFive<E> implements Predicate<Integer> {

    @Override
    public boolean test(Integer v) {
        
        Integer five = 5;
        
        return v > five;
    }
}

This is a Java class implementing the Predicate<Integer> interface. Its test() method returns true for values bigger than five.

List<Integer> nums = Arrays.asList(2, 3, 1, 5, 6, 7, 8, 9, 12);

We have a list of integer values.

BiggerThanFive btf = new BiggerThanFive();

A BiggerThanFive is instantiated.

nums.stream().filter(btf).forEach(System.out::println);

The predicate object is passed to the filter() method to get all values from the list that are bigger than five.

6
7
8
9
12

This is the output.

Java Predicate with lambda

Java lambda expression simplifies the creation of Java Predicates.

JavaPredicateEx2.java
package com.zetcode;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class JavaPredicateEx2 {

    public static void main(String[] args) {

        List<Integer> nums = Arrays.asList(2, 3, 1, 5, 6, 7, 8, 9, 12);
        
        Predicate<Integer> btf = n -> n > 5;
        
        nums.stream().filter(btf).forEach(System.out::println);
    }
}

The example filters integer values; this time we use Java lambda expression, which makes the code much shorter.

Predicate<Integer> btf = n -> n > 5;

This is a one-liner that creates the predicate.

Java Predicate example II

The next example uses a predicate with two conditions.

Country.java
package com.zetcode;

public class Country {
    
    private String name;
    private int population;

    public Country(String name, int population) {
        this.name = name;
        this.population = population;
    }

    public String getName() {
        return name;
    }

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

    public int getPopulation() {
        return population;
    }

    public void setPopulation(int population) {
        this.population = population;
    }

    @Override
    public String toString() {
        return "Country{" + "name=" + name + 
                ", population=" + population + '}';
    }
}

We have a Country class; it has name and population attributes.

JavaPredicateEx3.java
package com.zetcode;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class JavaPredicateEx3 {

    public static void main(String[] args) {
        
        List<Country> countries = new ArrayList<>();

        countries.add(new Country("Iran", 80840713));
        countries.add(new Country("Hungary", 9845000));
        countries.add(new Country("Poland", 38485000));
        countries.add(new Country("India", 1342512000));
        countries.add(new Country("Latvia", 1978000));
        countries.add(new Country("Vietnam", 95261000));
        countries.add(new Country("Sweden", 9967000));
        countries.add(new Country("Iceland", 337600));
        countries.add(new Country("Israel", 8622000)); 
        
        Predicate<Country> p1 = c -> c.getName().startsWith("I") && 
                c.getPopulation() > 10000000;
        
        countries.stream().filter(p1).forEach(System.out::println);
    }
}

In the example, we create a list of countries. We filter the list by the country name and population.

Predicate<Country> p1 = c -> c.getName().startsWith("I") && 
        c.getPopulation() > 10000000;

The predicate returns true for countries that start with 'I' and their population is over ten million.

Country{name=Iran, population=80840713}
Country{name=India, population=1342512000}

Two countries from the list fulfill the conditions: Iran and India.

Java IntPredicate

IntPredicate represents a predicate of one int-valued argument. This is the int-consuming primitive type specialization of Predicate<E>.

IntPredicateEx.java
package com.zetcode;

import java.util.Arrays;
import java.util.function.IntPredicate;

public class IntPredicateEx {

    public static void main(String[] args) {
        
        int nums[] = { 2, 3, 1, 5, 6, 7, 8, 9, 12 };
        
        IntPredicate p = n -> n > 5;

        Arrays.stream(nums).filter(p).forEach(System.out::println);
    }
}

The example filters an array of int values with filter() and IntPredicate.

int nums[] = { 2, 3, 1, 5, 6, 7, 8, 9, 12 };

We define an array of integers.

IntPredicate p = n -> n > 5;

An IntPredicate is created; it returns true for int values bigger than five.

Arrays.stream(nums).filter(p).forEach(System.out::println);

We create a stream from the array and filter the elemetnts. The filter() method receives the predicate as a parameter.

Composing predicates

With and() and or() methods we can compose predicates in Java.

JavaPredicateCompose.java
package com.zetcode;

import java.util.Arrays;
import java.util.function.IntPredicate;

public class JavaPredicateCompose {

    public static void main(String[] args) {

        int nums[] = {2, 3, 1, 5, 6, 7, 8, 9, 12};
        
        IntPredicate p1 = n -> n > 3;
        IntPredicate p2 = n -> n < 9;
        
        Arrays.stream(nums).filter(p1.and(p2)).forEach(System.out::println);
        
        System.out.println("**********");
        
        IntPredicate p3 = n -> n == 6;
        IntPredicate p4 = n -> n == 9;
        
        Arrays.stream(nums).filter(p3.or(p4)).forEach(System.out::println);
    }
}

The example filters data using composition of IntPredicates.

IntPredicate p1 = n -> n > 3;
IntPredicate p2 = n -> n < 9;

Arrays.stream(nums).filter(p1.and(p2)).forEach(System.out::println);

We combine two predicates with the and() method; we get integers that are bigger than three and smaller than nine.

IntPredicate p3 = n -> n == 6;
IntPredicate p4 = n -> n == 9;

Arrays.stream(nums).filter(p3.or(p4)).forEach(System.out::println);

With the or() method, we get values that are equal either to six or nine.

5
6
7
8
**********
6
9

This is the output.

Negating predicates

The negate() method returns a predicate that represents the logical negation of the given predicate.

JavaPredicateNegate.java
package com.zetcode;

import java.util.Arrays;
import java.util.function.IntPredicate;

public class JavaPredicateNegate {

    public static void main(String[] args) {

        int nums[] = { 2, 3, 1, 5, 6, 7, 8, 9, 12 };
        
        IntPredicate p = n -> n > 5;
        
        Arrays.stream(nums).filter(p).forEach(System.out::println);
        
        System.out.println("**********");
        
        Arrays.stream(nums).filter(p.negate()).forEach(System.out::println);
    }
}

The example demonstrates the usage of the negate() method.

IntPredicate p = n -> n > 5;

We have a predicate that returns true for values bigger than five.

Arrays.stream(nums).filter(p).forEach(System.out::println);

We filter all integers that are bigger than five.

Arrays.stream(nums).filter(p.negate()).forEach(System.out::println);

With the negate() method, we get the opposite: values lower or equal to four.

6
7
8
9
12
**********
2
3
1
5

This is the output of the example.

In this tutorial, we have worked with Java Predicates. You might also be interested in the related tutorials: Java tutorial, HashMap iteration in Java, Java ArrayList tutorial, Java HashSet tutorial, Java static keyword, Java 8 forEach tutorial, Reading text files in Java, and Reading and writing ICO images in Java.