Prädikat in Java


100

Ich gehe den Code durch, der Predicatein Java verwendet wird. Ich habe noch nie benutzt Predicate. Kann mich jemand zu einem Tutorial oder einer konzeptionellen Erklärung Predicateund deren Implementierung in Java führen?


4
Sprechen Sie über Guaven Predicate? Sowas ähnliches? Etwas ganz anderes?
Polygenelubricants

2
Es gibt auch Apache CommonsPredicate
Dan Gravell

Antworten:


203

Ich gehe davon aus, dass Sie com.google.common.base.Predicate<T>von Guave sprechen .

Aus der API:

Bestimmt einen trueoder falseWert für eine bestimmte Eingabe. Beispielsweise RegexPredicatekönnte a implementieren Predicate<String>und true für jede Zeichenfolge zurückgeben, die dem angegebenen regulären Ausdruck entspricht.

Dies ist im Wesentlichen eine OOP-Abstraktion für einen booleanTest.

Beispielsweise haben Sie möglicherweise eine Hilfsmethode wie die folgende:

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

Mit a List<Integer>können Sie jetzt nur die geraden Zahlen wie folgt verarbeiten:

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

Mit Predicatedemif Test als Typ abstrahiert. Auf diese Weise kann es mit dem Rest der API zusammenarbeiten, z. B. Iterablesmit vielen Dienstprogrammmethoden Predicate.

So können Sie jetzt so etwas schreiben:

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

Beachten Sie, dass die for-each-Schleife jetzt ohne den ifTest viel einfacher ist . Wir haben durch Definieren ein höheres Maß an Abtraktion erreichtIterable<Integer> evenNumbers von filter-ing eine Verwendung Predicate.

API-Links


Bei Funktion höherer Ordnung

Predicateermöglicht Iterables.filteres, als sogenannte Funktion höherer Ordnung zu dienen. Dies allein bietet viele Vorteile. Nehmen Sie das List<Integer> numbersobige Beispiel. Angenommen, wir möchten testen, ob alle Zahlen positiv sind. Wir können so etwas schreiben:

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

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

Mit a Predicateund in Zusammenarbeit mit den übrigen Bibliotheken können wir stattdessen Folgendes schreiben:

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

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

Hoffentlich können Sie jetzt den Wert in höheren Abstraktionen für Routinen wie "Alle Elemente nach dem angegebenen Prädikat filtern", "Überprüfen, ob alle Elemente das angegebene Prädikat erfüllen" usw. sehen, um besseren Code zu erhalten.

Leider hat Java keine erstklassigen Methoden: Sie können keine Methoden an Iterables.filterund weitergeben Iterables.all. Sie können natürlich Objekte in Java weitergeben. Somit wird der PredicateTyp definiert und Sie übergeben stattdessen Objekte, die diese Schnittstelle implementieren.

Siehe auch


4
Ich bezog mich nicht auf Guavas Prädikat, ich hätte in meiner Frage klar sein sollen. Aber Ihre Erklärung half mir zu verstehen, wonach ich suchte, wie Prädikatenlogik in Java verwendet wird. Vielen Dank für die ausführliche Erklärung
Srikanth

@polygenelubricants, Warum erfinden, Predicate<Integer>wenn wir bereits haben, F<Integer, Boolean>was genau das Gleiche tut?
Pacerier

Sie können es auch auf Java 8-Art tun: 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

Ein Prädikat ist eine Funktion, die einen True / False-Wert (dh einen Booleschen Wert) zurückgibt, im Gegensatz zu einem Satz, der ein True / False-Wert (dh ein Boolescher Wert) ist. In Java kann man keine eigenständigen Funktionen haben. Daher erstellt man ein Prädikat, indem man eine Schnittstelle für ein Objekt erstellt, das ein Prädikat darstellt, und stellt dann eine Klasse bereit, die diese Schnittstelle implementiert. Ein Beispiel für eine Schnittstelle für ein Prädikat könnte sein:

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

Und dann haben Sie möglicherweise eine Implementierung wie:

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

Um ein besseres konzeptionelles Verständnis zu erhalten, sollten Sie sich mit Logik erster Ordnung befassen.

Bearbeiten In der Java-API ist ab Java 8
eine Standard- Prädikatschnittstelle ( java.util.function.Predicate ) definiert. Vor Java 8 ist es möglicherweise zweckmäßig, die Schnittstelle com.google.common.base.Predicate von wiederzuverwenden Guave .

Beachten Sie außerdem, dass es ab Java 8 viel einfacher ist, Prädikate mithilfe von Lambdas zu schreiben. In Java 8 und höher kann beispielsweise p -> trueeine Funktion übergeben werden, anstatt eine benannte Tautologie-Unterklasse wie oben definiert zu definieren.


0

Sie können die Ansicht java doc Beispiele oder das Beispiel der Verwendung von Prädikats hier

Grundsätzlich wird es verwendet, um Zeilen in der Ergebnismenge basierend auf bestimmten Kriterien zu filtern und true für die Zeilen zurückzugeben, die Ihren Kriterien entsprechen:

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

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

Ich bezog mich auf das Commons-Prädikat, nicht auf die Ergebnismenge. danke aber
srikanth

0

Addiert zu dem, was Micheal gesagt hat:

Sie können Predicate wie folgt verwenden, um Sammlungen in Java zu filtern:

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

Ein mögliches Prädikat kann sein:

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

Verwendung:

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

1
Besiegt das nicht im Grunde genommen den Zweck? Der Hauptgrund für die Wahl eines funktionalen Ansatzes besteht darin, NICHT manuell zu iterieren und das for loszuwerden. Die Abstraktionsebene wird höher und leistungsfähiger - wenn Sie dies jedoch manuell tun, wird dieser Zweck zunichte gemacht, und Sie kehren zur Abstraktionsebene auf niedriger Ebene zurück.
Eugen
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.