Geralmente predicado significa uma declaração que determina se um valor pode ser verdadeiro ou falso. Na programação, predicados significam funções com um argumento que retornam um valor booleano. Functional Interface Predicate foi realizado em Java 8. “Funcional” significa que contém apenas um método abstrato. Ele aceita um argumento e retorna um booleano. Em Java, as interfaces funcionais são usadas para lidar com expressões Lambda, construtores e referências de métodos. Normalmente, o Java 8 Predicate é usado para aplicar um filtro a uma coleção de objetos. Vamos dar uma olhada em suas principais aplicações e métodos amplamente utilizados, bem como resolver alguns problemas práticos. Predicado Java com Exemplos - 1

Por que os desenvolvedores usam predicado

Basicamente, os desenvolvedores podem usar predicados para qualquer tarefa que envolva avaliar itens com base em critérios predefinidos e retornar um valor booleano. Aqui estão os exemplos de tarefas simples que os desenvolvedores manipulam usando predicados:
  • Filtrando um conjunto de inteiros.
  • Classificar listas garantindo que os dados estejam em conformidade com várias condições predefinidas (por exemplo, organizar uma variedade de itens definindo condições de preço e peso).
  • Usando pacotes utilitários em programação concorrente.
Os predicados são uma característica importante no teste de software. A interface funcional facilita a separação de unidades para teste, melhora a legibilidade e a capacidade de gerenciamento do código do aplicativo.

Sintaxe de predicado em Java

java.util.function.Predicate foi introduzido no Java 8 como uma forma alternativa de lidar com impressões de avaliação no Lambda. A exibição padrão da interface é Predicate<T> , em que T é um único argumento que retorna um valor booleano. Os Predicados Java possuem um método funcional (abstrato) test(Object) que avalia esse predicado em um determinado Objeto.

@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Aqui está um exemplo de como escrever um predicado simples que filtra números inteiros com base nas condições “maior que”, “menor que”.

// An example of a simple Java predicate
  
import java.util.function.Predicate; 
public class PredicateExample { 
    public static void main(String[] args) 
    { 
        // Creating predicate 
        Predicate<Integer> lesserThan = i -> (i < 18);  
  
        // Calling Predicate method 
        System.out.println(lesserThan.test(10));  
    }
}
A saída será verdadeira porque 10 < 18. Mais um exemplo com Predicado em filter() . O predicado ajuda a filtrar todos os adultos da lista de idades.

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

  public class PredicateExample {
      public static void main(String[] args) {
          List<Integer> ages = List.of(17, 18, 19, 28, 18, 28, 46, 7, 8, 9, 21, 12);
          NotLessThan18<Integer> isAdult = new NotLessThan18<>();
          ages.stream().filter(isAdult).forEach(System.out::println);
      }
  }



class NotLessThan18<E> implements Predicate<Integer> {

      @Override
      public boolean test(Integer v) {
          Integer ADULT = 18;
          return v >= ADULT;
      }
  }
A saída é:
18 19 28 18 28 46 21

Métodos de predicados do Java 8

A interface Predicate tem um punhado de métodos.
  • boolean test(T t) avalia o predicado no argumento dado.
  • default Predicate<T> and(Predicate<? super T> other) retorna um predicado que representa um AND lógico em curto-circuito deste predicado e outro.
  • default Predicate<T> ou retorna um predicado composto que representa um OR lógico de curto-circuito deste predicado e outro.
  • default Predicate<T> negate() retorna um predicado que é logicamente oposto a este predicado.
  • padrão Predicate<T> isEqual(Object targetRef) retorna um resultado do teste se dois argumentos são iguais de acordo com Objects.equals(Object, Object) .

teste booleano(T t)

Este é um método funcional para predicados Java que avalia se um determinado argumento satisfaz ou não a condição de um predicado. Exemplo: aqui criamos um predicado adulto para todos os que têm 18 anos ou mais. O método test() obtém um valor inteiro e o verifica.

import java.util.function.Predicate;
public class PredicateTestTest {
   public static void main(String[] args) {
       Predicate<Integer> adult = i -> i >= 18;
       System.out.println(adult.test(12));
       System.out.println(adult.test(19));
       System.out.println(adult.test(21));
   }
}
Qual será a saída para o código acima? No primeiro caso, como 12 é menor que 18, será falso. Quanto ao segundo e ao terceiro cenário, estão reunidas as condições para que o retorno seja verdadeiro.
falso verdadeiro verdadeiro

predicado padrão.and()

Este método representa o operador “e”. É por isso que, se um dos predicados fornecidos não atender a uma condição definida, outro não será avaliado. Exemplo: vamos compor predicados em Java, filtrando todas as pessoas que já são adultas mas com menos de 65 anos usando and() . Vamos usar predicate.add () e escrever um predicado java com lambda para estas condições: Se a condição for verdadeira, o aplicativo retornará a seguinte instrução:

import java.util.function.Predicate;

   public class PredicateDemo {
       public static void main(String[] args) {
           Predicate<Integer> adultYet = i -> i >= 18;
           Predicate<Integer> adultStill = i -> i < 65;
           System.out.println(adultYet.and(adultStill).test(5));
           System.out.println(adultYet.and(adultStill).test(38));
           System.out.println(adultYet.and(adultStill).test(90));
       }
   }
A saída é:
falso verdadeiro falso

predicado padrão.or()

O método Predicate.or() representa o operador “OR”. Isso significa que a condição permanecerá verdadeira mesmo se um dos dois predicados for verdadeiro e o outro for falso. Exemplo: vamos avaliar strings de caracteres agora. Tente usar o método OR para classificar todas as frases que contêm substring “my” ou “crayon”.

import java.util.function.Predicate;

  public class PredicateDemo2 {
      public static void main(String[] args) {
          Predicate<String> containsA = t -> t.contains("crayon");
          Predicate<String> containsB = t -> t.contains("my");
          System.out.println(containsA.or(containsB).test("here is my crayon"));
          System.out.println(containsA.or(containsB).test("here is my pencil"));
          System.out.println(containsA.or(containsB).test("here is John's crayon"));
          System.out.println(containsA.or(containsB).test("here is John's pencil"));
      }
  }
A saída é:
verdadeiro verdadeiro verdadeiro falso

predicado padrão negate()

O método negate() é usado para reunir todos os valores que não obedecem a critérios pré-definidos. Exemplo: se você deseja classificar a classe “Tomates” e encontrar todas as entradas que não são “Red”, você pode escrever um Predicado e rapidamente percorrer toda a sequência. Tente escrever o código para este por conta própria e compare-o com a solução assim que terminar.

import java.util.function.Predicate;

public class PredicateDemo3 {
public static void main(String[] args) {
 Predicate<Integer> adult = i -> i >= 18;
System.out.println(adult.negate().test(7));  System.out.println(adult.negate().test(19))
  }
   }
A saída é:
verdadeiro falso

Predicado estático isEqual(Object targetRef)

Este método é muito útil se você deseja determinar se dois objetos são iguais a um valor definido como um parâmetro de Objects.equals(). Esse método é especialmente útil se você precisar comparar resultados de testes semelhantes. Exemplo: digamos que você está comparando dois carrinhos de peras e quer ter certeza se ambos têm frutas de peso e cor padrão. Neste caso, static Predicate isEqual(Object targetRef) é exatamente o método que você precisa. Vamos dar uma olhada em como isEqual verifica a igualdade de duas strings:

import java.util.function.Predicate;

public class PredicateDemo2 {
   public static void main(String[] args) {
       Predicate<String> i = Predicate.isEqual("here is my crayon");
       System.out.println(i.test("here is my pencil"));
       System.out.println(i.test("here is my crayon"));
   }
}
Se um objeto que você está analisando estiver de acordo com as condições padrão, a função retornará true. A saída é:
falso verdadeiro

Java IntPredicate

Java IntPredicate é uma interface funcional, portanto, você pode usá-la como destino de atribuição para uma expressão lambda ou referência de método. IntPredicate opera em um número inteiro e retorna um valor de predicado com base em uma condição. Tal como a interface Predicate, IntPredicate também possui métodos test() , and() , negate() , or() . Aqui está um exemplo de IntPredicate. Ele também filtra todos os adultos (18 ou mais) da matriz.

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

public class IntPredicateExample {

   public static void main(String[] args) {

       int[] ages = { 18, 28, 18, 46, 90, 45, 2, 3, 1, 5, 7, 21, 12 };

       IntPredicate p = n -> n >= 18;

       Arrays.stream(ages).filter(p).forEach(System.out::println);
   }
}
A saída é:
18 28 18 46 90 45 21

Escrevendo predicados limpos em Java

Java Predicados são altamente funcionais e divertidos de se trabalhar. No entanto, a menos que você esteja ciente de como as expressões lambda que você escreve afetam o código, existe o risco de reduzir a capacidade de manutenção do código com predicados confusos. Aqui estão algumas práticas simples que ajudarão você a garantir que suas interfaces funcionais sejam fáceis de gerenciar e ler.
  • Não se repita — não componha predicados com Java com valores, métodos e condições repetidos mais de uma vez. Dessa forma, você desperdiça seu tempo produtivo e torna o código confuso.
  • Separe os predicados do código do aplicativo para garantir a testabilidade. Fora isso, crie um cronograma de teste de unidade de predicado e cumpra-o.
  • Use importações e padrões de composição para garantir que suas aulas não fiquem inchadas e sejam fáceis de gerenciar.
  • Considere mover predicados Java para classes Helper — dessa forma, você melhora a capacidade de reutilização de seu código e facilita a manutenção.
  • Legibilidade — sempre que possível, prefira declarações de uma linha a predicados complexos. Pode ser tentador mostrar sua compreensão de interfaces funcionais complexas. No entanto, quando se trata de manutenção, menos é mais.