1. Was ist ein Predicate?
Ein Predicate
ist ein funktionales Interface in Java 8, das eine Bedingung prüft und einen boolean
DayOfWeek
zurückgibt: true
oder false
. Es hat eine einzige abstrakte Methode:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Das bedeutet, dass ein Predicate verwendet wird, um eine Bedingung auf eine Eingabe vom Typ T
anzuwenden und zu prüfen, ob sie erfüllt ist.
2. Einfaches Beispiel für Predicate
Hier ein einfaches Beispiel, um zu demonstrieren, wie ein Predicate funktioniert:
Predicate<Integer> isEven = n -> n % 2 == 0; // Prüft, ob eine Zahl gerade ist
System.out.println(isEven.test(4)); // true
System.out.println(isEven.test(5)); // false
3. Predicates kombinieren
Java 8 ermöglicht es dir, Predicates zu kombinieren. Dafür gibt es drei Hauptmethoden:
and()
: Kombiniert zwei Predicates und gibttrue
zurück, wenn beide Predicatestrue
sind.or()
: Kombiniert zwei Predicates und gibttrue
zurück, wenn mindestens eines der Predicatestrue
ist.negate()
: Gibt ein Predicate zurück, das das Gegenteil eines gegebenen Predicates ist.
4. Predicate chaining: AND-Beispiel
Die and()
Methode erlaubt es, zwei Predicates zu kombinieren, sodass die Bedingung nur erfüllt wird, wenn beide Predicates true
zurückgeben:
Predicate<Integer> isPositive = n -> n > 0;
Predicate<Integer> isEven = n -> n % 2 == 0;
Predicate<Integer> isPositiveAndEven = isPositive.and(isEven);
System.out.println(isPositiveAndEven.test(4)); // true
System.out.println(isPositiveAndEven.test(-4)); // false
System.out.println(isPositiveAndEven.test(5)); // false
5. Predicate chaining: OR-Beispiel
Die or()
Methode erlaubt es, zwei Predicates zu kombinieren, sodass die Bedingung erfüllt wird, wenn mindestens eines der Predicates true
zurückgibt:
Predicate<Integer> isNegative = n -> n < 0;
Predicate<Integer> isEven = n -> n % 2 == 0;
Predicate<Integer> isNegativeOrEven = isNegative.or(isEven);
System.out.println(isNegativeOrEven.test(4)); // true
System.out.println(isNegativeOrEven.test(-5)); // true
System.out.println(isNegativeOrEven.test(5)); // false
6. Predicate chaining: NEGATE-Beispiel
Die negate()
Methode gibt ein Predicate zurück, das das Gegenteil eines gegebenen Predicates ist:
Predicate<Integer> isPositive = n -> n > 0;
Predicate<Integer> isNotPositive = isPositive.negate();
System.out.println(isNotPositive.test(4)); // false
System.out.println(isNotPositive.test(-4)); // true
7. Komplexere Beispiele und Anwendungen
Man kann diese Methoden kombinieren, um komplexere logische Bedingungen zu erstellen:
Predicate<String> isNotNull = Objects::nonNull;
Predicate<String> isNotEmpty = s -> !s.isEmpty();
Predicate<String> hasLengthOf5 = s -> s.length() == 5;
Predicate<String> complexPredicate = isNotNull.and(isNotEmpty).and(hasLengthOf5);
System.out.println(complexPredicate.test("Hello")); // true
System.out.println(complexPredicate.test("Hi")); // false
System.out.println(complexPredicate.test("")); // false
System.out.println(complexPredicate.test(null)); // false
8. Verwendung in Streams
Predicates sind besonders nützlich in Kombination mit Java Streams, da sie zur Filterung von Daten genutzt werden können:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, -1, -2, -3);
List<Integer> positiveNumbers = numbers.stream()
.filter(isPositive)
.collect(Collectors.toList());
System.out.println(positiveNumbers); // [1, 2, 3, 4, 5]
9. Best Practices
- Leserlichkeit: Kette nur so viele Predicates wie nötig, um die Leserlichkeit deines Codes zu gewährleisten.
- Wiederverwendbarkeit: Definiere Predicates als separate Variablen und kombiniere diese, um sie wiederverwenden zu können.
- Debugging: Nutze aussagekräftige Namen für deine Predicates, um leichter debuggen zu können.
Mit diesen grundlegenden Kenntnissen zu Predicates und ihren Kombinationsmöglichkeiten solltest du in der Lage sein, 80% der Funktionalitäten in praktischen Anwendungen zu nutzen. Viel Erfolg beim Anwenden von Predicate Chains in deinen Projekten!