CodeGym /Java-Blog /Germany /Java Predicate mit Beispielen
Autor
Artem Divertitto
Senior Android Developer at United Tech

Java Predicate mit Beispielen

Veröffentlicht in der Gruppe Germany
Im Allgemeinen ist ein Prädikat eine Aussage, die bestimmt, ob ein Wert wahr oder falsch sein kann. In der Programmierung sind Prädikate Funktionen mit einem Argument, die einen booleschen Wert zurückgeben. Das funktionale Interface Predicate wurde in Java 8 eingeführt. „Funktional“ bedeutet, dass es nur eine abstrakte Methode enthält. Es nimmt ein Argument entgegen und gibt einen booleschen Wert zurück. In Java werden funktionale Interfaces für den Umgang mit Lambda-Ausdrücken, Konstruktoren und Methodenreferenzen verwendet. Normalerweise wird Java 8 Predicate verwendet, um einen Filter auf eine Sammlung von Objekten anzuwenden. Werfen wir einen Blick auf die wichtigsten Anwendungen und weit verbreiteten Methoden und lösen wir einige Übungsaufgaben.Java Predicate mit Beispielen - 1

Warum Entwickler Predicate verwenden

Grundsätzlich können Entwickler Prädikate für alle Aufgaben verwenden, bei denen es darum geht, Elemente anhand von vordefinierten Kriterien zu bewerten und einen booleschen Wert zurückzugeben. Hier ein paar Beispiele für einfache Aufgaben, die Entwickler mit Prädikaten erledigen:
  • Filtern einer Menge von Ganzzahlen.
  • Sortieren von Listen, indem sichergestellt wird, dass die Daten mehreren vordefinierten Bedingungen entsprechen (z. B. Sortieren einer Reihe von Artikeln durch Festlegen von Preis- und Gewichtsbedingungen).
  • Die Verwendung von Hilfspaketen bei der nebenläufigen Programmierung.
Prädikate sind ein wichtiges Merkmal bei Softwaretests. Das funktionale Interface erleichtert die Trennung der Units für Tests und verbessert die Lesbarkeit und Handhabbarkeit des Anwendungscodes.

Prädikat-Syntax in Java

java.util.function.Predicate wurde in Java 8 als alternative Möglichkeit eingeführt, Bewertungseindrücke in Lambda zu behandeln. Die Standardansicht des Interfaces ist Predicate<T>, wobei T ein einzelnes Argument ist, das einen booleschen Wert zurückgibt. Java-Prädikate haben eine funktionale (abstrakte) Methode test(Object), die das Prädikat für ein bestimmtes Objekt auswertet.

@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Hier ist ein Beispiel für ein einfaches Prädikat, das ganze Zahlen anhand der Bedingungen „größer als“ und „kleiner als“ filtert.

// 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));  
    }
}
Die Ausgabe wird true sein, weil 10 < 18. Ein weiteres Beispiel mit Predicate in filter(). Das Prädikat hilft dabei, alle Erwachsenen aus der Liste der Altersgruppen herauszufiltern.

  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;
      }
  }
Die Ausgabe ist:
18 19 28 18 28 46 21

Java 8 Prädikatmethoden

Das Predicate-Interface hat eine Handvoll Methoden.
  • boolean test(T t) wertet das Prädikat für das angegebene Argument aus.
  • default Predicate<T> and(Predicate<? super T> other) gibt ein Prädikat zurück, das eine logische UND-Verknüpfung dieses Prädikats mit einem anderen darstellt.
  • default Predicate<T> or gibt ein zusammengesetztes Prädikat zurück, das ein kurzschließendes logisches ODER dieses Prädikats und eines anderen darstellt.
  • default Predicate<T> negate() gibt ein Prädikat zurück, das die logische Umkehrung dieses Prädikats ist.
  • ddefault Predicate<T> isEqual(Object targetRef) gibt ein Ergebnis der Prüfung zurück, ob zwei Argumente gemäß Objects.equals(Object, Object) gleich sind.

boolean test(T t)

Dies ist eine funktionale Methode für Java-Prädikate, die auswertet, ob ein gegebenes Argument die Bedingung eines Prädikats erfüllt oder nicht. Beispiel: Hier erstellen wir ein Prädikat „adult“ für alle, die 18 Jahre oder älter sind. Die test()-Methode erhält einen ganzzahligen Wert und überprüft ihn.

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));
   }
}
Wie sieht die Ausgabe für den obigen Code aus? Im ersten Fall ist 12 kleiner als 18, also ist es „false“. Im zweiten und dritten Szenario sind die Bedingungen erfüllt, sodass die Rückgabe „true“ sein wird.
false true true

default Predicate.and()

Diese Methode stellt den „und“-Operator dar. Wenn eines der Prädikate eine bestimmte Bedingung nicht erfüllt, wird ein anderes nicht bewertet. Beispiel: Wir wollen nun Prädikate in Java miteinander verbinden und mit and() alle Menschen herausfiltern, die bereits erwachsen, aber jünger als 65 sind. Verwenden wir predicate.add () und schreiben wir ein Java-Prädikat mit Lambda für diese Bedingungen: Wenn die Bedingung erfüllt ist, gibt die Anwendung die folgende Anweisung zurück:

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));
       }
   }
Die Ausgabe ist:
false true false

default Predicate.or()

Die Methode Predicate.or() stellt den „oder“-Operator dar. Das bedeutet, dass die Bedingung auch dann erfüllt bleibt, wenn eines der beiden Prädikate wahr und das andere falsch ist. Beispiel: Wir wollen jetzt Zeichenketten auswerten. Versuche, mit der „or“-Methode alle Sätze zu sortieren, die die Teilzeichenkette „mein“ oder „Buntstift“ enthalten.

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"));
      }
  }
Die Ausgabe ist:
true true true false

default Predicate negate()

Die negate()-Methode wird verwendet, um alle Werte zu sammeln, die nicht den vordefinierten Kriterien entsprechen. Beispiel: Wenn du die Klasse „Tomaten“ sortieren und alle Einträge finden willst, die nicht „Rot“ sind, kannst du ein Prädikat schreiben und schnell die gesamte Sequenz durchsuchen. Versuche, den Code für diese Aufgabe selbst zu schreiben und vergleiche ihn mit der Lösung, wenn du fertig bist.

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))
  }
   }
Die Ausgabe ist:
true false

static Predicate isEqual(Object targetRef)

Diese Methode ist sehr nützlich, wenn du feststellen willst, ob zwei Objekte gleich einem Wert sind, der als Parameter von Objects.equals() definiert ist. Diese Methode ist besonders nützlich, wenn du ähnliche Testergebnisse vergleichen musst. Beispiel: Angenommen, du vergleichst zwei Ladungen mit Birnen und möchtest sicherstellen, dass beide Früchte ein einheitliches Gewicht und eine einheitliche Farbe haben. In diesem Fall ist static Predicate isEqual(Object targetRef) genau die Methode, die du brauchst. Schauen wir uns an, wie isEqual die Gleichheit zweier Strings überprüft:

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"));
   }
}
Wenn ein Objekt, das du analysierst, die Standardbedingungen erfüllt, gibt die Funktion „true“ zurück. Die Ausgabe ist:
false true

Java IntPredicate

Java IntPredicate ist ein funktionales Interface, du kannst es also als Zuweisungsziel für einen Lambda-Ausdruck oder eine Methodenreferenz verwenden. IntPredicate arbeitet mit einer Ganzzahl und gibt einen Prädikatswert zurück, der auf einer Bedingung basiert. Wie das Predicate-Interface hat auch IntPredicate die Methoden test(), and(), negate() und or(). Hier ist ein Beispiel für IntPredicate. Es filtert ebenfalls alle Erwachsenen (18 oder mehr) aus dem Array.

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);
   }
}
Die Ausgabe ist:
18 28 18 46 90 45 21
Java Predicate mit Beispielen - 2

Saubere Prädikate in Java schreiben

Java-Prädikate sind sehr funktional und es macht Spaß, damit zu arbeiten. Wenn du jedoch nicht darauf achtest, wie sich Lambda-Ausdrücke, die du schreibst, auf den Code auswirken, besteht die Gefahr, dass die Wartbarkeit des Codes durch unübersichtliche Prädikate beeinträchtigt wird. Hier sind ein paar einfache Vorgehensweisen, mit denen du sicherstellen kannst, dass deine funktionalen Interfaces einfach zu verwalten und zu lesen sind.
  • Wiederhole dich nicht – setze keine Prädikate mit Java zusammen, in denen sich Werte, Methoden und Bedingungen mehr als einmal wiederholen. Auf diese Weise verschwendest du deine produktive Zeit und machst den Code unübersichtlich.
  • Trenne die Prädikate vom Anwendungscode, um die Testbarkeit zu gewährleisten. Außerdem solltest du einen Zeitplan für Unit-Tests aufstellen und dich daran halten.
  • Verwende Importe und Kompositionsmuster, um sicherzustellen, dass deine Klassen nicht aufgebläht werden und einfach zu verwalten sind.
  • Erwäge, Java-Prädikate in Hilfsklassen zu verschieben – so verbesserst du die Wiederverwendbarkeit deines Codes und erleichterst die Wartung.
  • Lesbarkeit – wann immer möglich, ziehe einzeilige Anweisungen komplexen Prädikaten vor. Es mag verlockend sein, mit deinem Verständnis für komplexe funktionale Interfaces zu prahlen. Aber wenn es um die Wartung geht, ist weniger auch hier mehr.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION