Saltar a contenido

Predicate

Predicate es una interfaz funcional que se encuentra en el paquete java.util.function. Mejora la capacidad de administración del código, ayuda a realizar pruebas unitarias por separado.

Se utiliza en expresiones lambda para comprobar si una condición dada es verdadera o falsa.

En lugar de pasar un booleano con valor true or false, pasas una referencia de tipo Predicate para determinar de manera dinámica si una condición dada es verdadera, o falsa.

Esta es la estructura de la interfaz Predicate:

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);
}

Como vemos la interfaz Predicate utiliza los genéricos para poder decirle que tipo concreto vamos a utilizar.

Ejemplo:

public class EjemploPredicate {
    public static void main(String[] args) {
        Predicate<String> checker = a -> a.startsWith("M");
        System.out.println(checker.test("Miguel"));
    }
}

Hemos creado un objeto Predicate de tipo String. Le damos cuerpo al método test con una expresión lambda que se le pasa un argumento y devuelve un booleano.

Métodos Predicate

La interfaz Predicate contiene algunos métodos como:

  • isEqual(Object targetRef): Devuelve un predicado que prueba si dos argumentos son iguales.
  • and(Predicate other): Devuelve un predicado compuesto que representa un AND lógico de este predicado y otro.
  • or(Predicate other): Devuelve un predicado compuesto que representa un OR lógico de este predicado y otro.
  • negate(): Devuelve un predicado que representa la negación lógica de este predicado.

Ejemplo:

    Predicate<Integer> greaterThan10 = i -> i > 10;
    Predicate<Integer> lessThan20 = i -> i < 20;
    System.out.println(greaterThan10.and(lessThan20).test(15));

    Predicate<Integer> greaterThanTen = (i) -> i > 10;
    Predicate<Integer> lowerThanTwenty = (i) -> i < 20;
    boolean resul = greaterThanTen.and(lowerThanTwenty).test(15);//true
    boolean resul2 = greaterThanTen.and(lowerThanTwenty).negate().test(15);//false

    Predicate<String> i  = Predicate.isEqual("asdf");
    System.out.println(i.test("java"));//false

Note

Debido al uso extendido de Predicate se han añadido las interfaces funcionales IntPredicate cuando queremos trabajar con predicados de tipo entero, DoublePredicate y LongPredicate. También tenemos la interfaz BiPredicate que es un caso especial de Predicate y recibe dos parámetros en vez de uno.

    IntPredicate predicate = (x) -> {
        if (x == 12345) {
            return true;
        }
        return false;
    };

    System.out.println(predicate.test(12345));

    IntPredicate intPredicate1 = predicate.negate();
    System.out.println(intPredicate1.test(12345));

    BiPredicate<String, Integer> filtroLongitud = (x, y) -> {
        return x.length() == y;
    };

    boolean result = filter.test("java", 10);
    System.out.println(result); // false

Supplier

Supplier es otra interfaz funcional dentro del paquete java.util.function que nos provee del método abstracto **get**, sin argumentos que devuelve un tipo de dato.

@FunctionalInterface
public interface Supplier<T> {

    T get();
}

Esta interfaz también se utiliza con expresiones lambda que no tienen parámetros pero devuelven un resultado:

    Random random = new Random();
    Supplier<Integer> su = () -> random.nextInt();

Al igual que ocurría en los predicados con los Supplier también disponemos de las clases IntSupplier, DoubleSupplier, LongSupplier y BooleanSupplier.

Consumer

Consumer es otra interfaz funcional dentro del paquete java.util.function que provee un método que recibe un solo parámetro de tipo genérico y no devuelve nada.

public interface Consumer<T> {
    void accept(T t);
}

La expresión lambda asignada a un objeto de tipo Consumer se usa para definir su método **accept(T t)** que eventualmente aplica la operación dada en su argumento. Los Consumer son útiles cuando no necesitan devolver ningún valor, ya que se espera que operen a través de efectos secundarios.

Existen también las interfaces IntConsumer, LongConsumer y DoubleConsumer.

Consumer<Integer> numero = (x) -> System.out.println(x);
numero.accept(5);

BiConsumer es un caso especial de las expresiones Consumer, son aquellas que reciben dos valores como parámetro y no devuelven resultado.

@FunctionalInterface
public interface BiConsumer<T, U> {
    void accept(T t, U u);
}

Ejemplo:

BiConsumer<Integer, String> biConsumer = (x, s) -> System.out.println(x + s);
biConsumer.accept(3, " puntos");