Predicato in Java


100

Sto esaminando il codice che utilizza Predicatein Java. Non l'ho mai usato Predicate. Qualcuno può guidarmi a qualsiasi tutorial o spiegazione concettuale Predicatee alla sua implementazione in Java?


4
Stai parlando di Guava's Predicate? Qualcosa di simile? Qualcos'altro completamente?
lubrificanti poligenici

2
C'è anche Apache CommonsPredicate
Dan Gravell

Risposte:


203

Presumo tu stia parlando di com.google.common.base.Predicate<T>Guava.

Dall'API:

Determina un valore trueo falseper un dato input. Ad esempio, a RegexPredicatepotrebbe implementare Predicate<String>e restituire true per qualsiasi stringa che corrisponde alla sua espressione regolare data.

Questa è essenzialmente un'astrazione OOP per un booleantest.

Ad esempio, potresti avere un metodo di supporto come questo:

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

Ora, dato un List<Integer>, puoi elaborare solo i numeri pari in questo modo:

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

Con Predicate, il iftest viene estratto come un tipo. Ciò gli consente di interagire con il resto dell'API, ad esempioIterables , che ha molti metodi di utilità che accettano Predicate.

Quindi, ora puoi scrivere qualcosa del genere:

    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);
    }

Nota che ora il ciclo for-each è molto più semplice senza il iftest. Abbiamo raggiunto un livello più alto di astrazione definendo Iterable<Integer> evenNumbers, filterutilizzando un Predicate.

Collegamenti API


Sulla funzione di ordine superiore

Predicatepermette Iterables.filterdi servire come quella che viene chiamata una funzione di ordine superiore. Di per sé, questo offre molti vantaggi. Prendi l' List<Integer> numbersesempio sopra. Supponiamo di voler verificare se tutti i numeri sono positivi. Possiamo scrivere qualcosa del genere:

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

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

Con un Predicate, e interagendo con il resto delle librerie, possiamo invece scrivere questo:

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

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

Si spera che ora tu possa vedere il valore in astrazioni più alte per routine come "filtra tutti gli elementi in base al predicato dato", "controlla se tutti gli elementi soddisfano il predicato dato", ecc. Per ottenere un codice migliore.

Sfortunatamente Java non ha metodi di prima classe: non puoi passare metodi a Iterables.filtere Iterables.all. Puoi, ovviamente, passare oggetti in Java. Pertanto, il Predicatetipo viene definito e si passano invece oggetti che implementano questa interfaccia.

Guarda anche


4
Non mi riferivo al Predicate di Guava, avrei dovuto essere chiaro nella mia domanda, ma la tua spiegazione mi ha aiutato a capire cosa stavo cercando, il modo in cui viene utilizzata la logica dei predicati in java. Grazie per l'elaborata spiegazione
srikanth

@polygenelubricants, perché inventare Predicate<Integer>quando abbiamo già F<Integer, Boolean>che fa esattamente la stessa cosa?
Pacerier

Potresti anche farlo alla maniera di java 8: List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Predicate<Integer> isEven = integer -> (integer % 2) == 0; Iterable<Integer> evenNumbers = numbers.stream().filter(isEven).collect(Collectors.toList());

14

Un predicato è una funzione che restituisce un valore vero / falso (cioè booleano), al contrario di una proposizione che è un valore vero / falso (cioè booleano). In Java, non è possibile avere funzioni autonome, quindi si crea un predicato creando un'interfaccia per un oggetto che rappresenta un predicato e quindi si fornisce una classe che implementa tale interfaccia. Un esempio di interfaccia per un predicato potrebbe essere:

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

E poi potresti avere un'implementazione come:

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

Per ottenere una migliore comprensione concettuale, potresti voler leggere la logica del primo ordine.

Modifica
Esiste un'interfaccia Predicate standard ( java.util.function.Predicate ) definita nell'API Java a partire da Java 8. Prima di Java 8, potresti trovare conveniente riutilizzare l' interfaccia com.google.common.base.Predicate da Guava .

Inoltre, si noti che a partire da Java 8, è molto più semplice scrivere predicati utilizzando lambda. Ad esempio, in Java 8 e versioni successive, è possibile passare p -> truea una funzione invece di definire una sottoclasse Tautology denominata come sopra.


0

È possibile visualizzare gli esempi di documentazione java o l'esempio di utilizzo di Predicate qui

Fondamentalmente viene utilizzato per filtrare le righe nel gruppo di risultati in base a criteri specifici che potresti avere e restituire true per quelle righe che soddisfano i tuoi criteri:

 // the age column to be between 7 and 10
    AgeFilter filter = new AgeFilter(7, 10, 3);

    // set the filter.
    resultset.beforeFirst();
    resultset.setFilter(filter);

Mi riferivo al predicato dei comuni, non al Resultset. grazie però
srikanth

0

In aggiunta a quanto ha detto Micheal :

È possibile utilizzare Predicate come segue per filtrare le raccolte in java:

public static <T> Collection<T> filter(final Collection<T> target,
   final Predicate<T> predicate) {
  final Collection<T> result = new ArrayList<T>();
  for (final T element : target) {
   if (predicate.apply(element)) {
    result.add(element);
   }
  }
  return result;
}

un possibile predicato può essere:

final Predicate<DisplayFieldDto> filterCriteria = 
                    new Predicate<DisplayFieldDto>() {
   public boolean apply(final DisplayFieldDto displayFieldDto) {
    return displayFieldDto.isDisplay();
   }
  };

Uso:

 final List<DisplayFieldDto> filteredList=
 (List<DisplayFieldDto>)filter(displayFieldsList, filterCriteria);

1
Questo fondamentalmente non sconfigge lo scopo? Il motivo principale nella scelta di un approccio funzionale è NON iterare manualmente e sbarazzarsi di for. Il livello di astrazione diventa più alto e più potente, tuttavia eseguire manualmente il per sconfigge quello scopo e torna all'astrazione di basso livello.
Eugen
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.