How to use Java 8 predicate

Las expresiones lambda son funciones anónimas, es decir que no necesitan una clase. Su sintaxis básica se muestra a continuación:

parámetros → {Cuerpo lambda}

En caso de que el cuerpo lambda presenta más de una línea de código, será necesario incluir las llaves. En caso devuelva un valor, será necesario incluir también la cláusula return.

A continuación, mostraré algunos ejemplos del uso de predicados utilizando funciones lambda. Recuerden que estas características sólo están disponibles en la versión 8 del JDK.

Predicado simple
Representa una función con un único argumento cuyo valor de retorno será de tipo booleano. Aplicaremos este caso para verificar si un número es primo o no.

import java.util.function.Predicate;
import java.util.stream.IntStream;

/**
 *
 * @author Rolando
 */
public class Main {

    public static void main(String[] args) {
        System.out.println(isPrimo(1));
        System.out.println(isPrimo(2));
        System.out.println(isPrimo(3));
        System.out.println(isPrimo(4));
    }

    private static boolean isPrimo(final int numero) {
        Predicate<Integer> isDivisible = divisor -> numero % divisor == 0;
        return numero > 1 && IntStream.range(2, numero).
                noneMatch(index -> isDivisible.test(index));
    }
}

Encadenamiento de predicados
Los predicados también puede ser encadenados entre sí utilizando conectores de tipo AND, OR y de negación como si de cualquier expresión lógica se tratase. A continuación, se muestra un ejemplo sencillo en donde se verifica, a través de dos predicados, que un número se encuentra en un rango determinado.
import java.util.function.Predicate;

/**
 *
 * @author Rolando
 */
public class Main {

    public static void main(String[] args) {
        System.out.println(isInRange(7, 2, 8));
        System.out.println(isInRange(9, 11, 15));
    }

    private static boolean isInRange(final int numero, final int limiteInferior, final int limiteSuperior) {
        Predicate<Integer> mayorNumero = i -> i >= limiteInferior;
        Predicate<Integer> menorNumero = i -> i <= limiteSuperior;
        return limiteSuperior >= limiteInferior && mayorNumero.and(menorNumero).test(numero);
    }
}

Predicados como argumentos de funciones
Java 8 también nos permite pasar predicados como argumentos de funciones. En el siguiente ejemplo, sólo vamos a permitir números que cumplan con la regla que es establecida como parámetro de la función procesar.
import java.util.function.Predicate;

/**
 *
 * @author Rolando
 */
public class Main {

    public static void main(String[] args) {
        procesar(11, (i) -> i > 10);
        procesar(9, (i) -> i % 3 == 0);
    }

    /**
     * Función que recibe un predicado como parámetro
     *
     * @param number
     * @param predicate
     */
    static void procesar(int number, Predicate<Integer> predicate) {
        if (predicate.test(number)) {
            System.out.println("Número " + number + " ha sido aceptado!");
        }
    }
}

También podemos filtrar elementos de una lista utilizando predicados. El siguiente ejemplo lo ilutra:
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
 *
 * @author Rolando
 */
public class Main {

    public static void main(String[] args) {
        List<Usuario> users = new ArrayList<>();
        users.add(new Usuario("John", "admin"));
        users.add(new Usuario("Peter", "member"));
        List<Usuario> lstAdministradores = process(users, (u) -> u.getUsuario().equals("admin"));
        System.out.println(lstAdministradores.size());
    }

    static List<Usuario> process(List<Usuario> users, Predicate<Usuario> predicate) {
        List<Usuario> result = new ArrayList<>();
        for (Usuario user : users) {
            if (predicate.test(user)) {
                result.add(user);
            }
        }
        return result;
    }
}

class Usuario {

    private String nombre;
    private String usuario;

    public Usuario(String nombre, String usuario) {
        this.nombre = nombre;
        this.usuario = usuario;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String getUsuario() {
        return usuario;
    }

    public void setUsuario(String usuario) {
        this.usuario = usuario;
    }
}

Comentarios