Java 8 Prädikatkette

1. Übersicht

In diesem kurzen Tutorial werden verschiedene Möglichkeiten zum Verketten von Prädikaten in Java 8 erläutert .

2. Grundlegendes Beispiel

Zuerst wollen wir mal sehen , wie ein einfaches verwenden Prädikats eine filtern Liste der Namen:

@Test public void whenFilterList_thenSuccess(){ List names = Arrays.asList("Adam", "Alexander", "John", "Tom"); List result = names.stream() .filter(name -> name.startsWith("A")) .collect(Collectors.toList()); assertEquals(2, result.size()); assertThat(result, contains("Adam","Alexander")); }

In diesem Beispiel haben wir unsere Namensliste so gefiltert , dass nur Namen, die mit „A“ beginnen, mit dem Prädikat belassen werden :

name -> name.startsWith("A")

Aber was wäre, wenn wir mehrere Prädikate anwenden wollten ?

3. Mehrere Filter

Wenn wir mehrere Prädikate anwenden möchten , besteht eine Option darin, einfach mehrere Filter zu verketten:

@Test public void whenFilterListWithMultipleFilters_thenSuccess(){ List result = names.stream() .filter(name -> name.startsWith("A")) .filter(name -> name.length() < 5) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }

Wir haben jetzt unser Beispiel aktualisiert, um unsere Liste zu filtern, indem wir Namen extrahieren, die mit "A" beginnen und eine Länge von weniger als 5 haben.

Wir haben zwei Filter verwendet - einen für jedes Prädikat .

4. Komplexes Prädikat

Anstatt mehrere Filter zu verwenden, können wir jetzt einen Filter mit einem komplexen Prädikat verwenden :

@Test public void whenFilterListWithComplexPredicate_thenSuccess(){ List result = names.stream() .filter(name -> name.startsWith("A") && name.length() < 5) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }

Diese Option ist flexibler als die erste, da wir bitweise Operationen verwenden können, um das Prädikat so komplex zu erstellen, wie wir möchten.

5. Prädikate kombinieren

Wenn wir kein komplexes Prädikat mit bitweisen Operationen erstellen möchten , verfügt Java 8 Predicate über nützliche Methoden, mit denen wir Prädikate kombinieren können .

Wir kombinieren Prädikate mit den Methoden Predicate.and () , Predicate.or () und Predicate.negate ().

5.1. Prädikat.und ()

In diesem Beispiel definieren wir unsere Prädikate explizit und kombinieren sie dann mit Predicate.and ():

@Test public void whenFilterListWithCombinedPredicatesUsingAnd_thenSuccess(){ Predicate predicate1 = str -> str.startsWith("A"); Predicate predicate2 = str -> str.length() < 5; List result = names.stream() .filter(predicate1.and(predicate2)) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }

Wie wir sehen können, ist die Syntax ziemlich intuitiv und die Methodennamen legen die Art der Operation nahe. Mit und () haben wir unsere Liste gefiltert, indem wir nur Namen extrahiert haben, die beide Bedingungen erfüllen.

5.2. Predicate.or ()

Wir können auch Predicate.or () verwenden , um Prädikate zu kombinieren .

Extrahieren wir Namen, die mit „J“ beginnen, sowie Namen mit einer Länge von weniger als 4:

@Test public void whenFilterListWithCombinedPredicatesUsingOr_thenSuccess(){ Predicate predicate1 = str -> str.startsWith("J"); Predicate predicate2 = str -> str.length() < 4; List result = names.stream() .filter(predicate1.or(predicate2)) .collect(Collectors.toList()); assertEquals(2, result.size()); assertThat(result, contains("John","Tom")); }

5.3. Predicate.negate ()

Wir können Predicate.negate () auch beim Kombinieren unserer Prädikate verwenden :

@Test public void whenFilterListWithCombinedPredicatesUsingOrAndNegate_thenSuccess(){ Predicate predicate1 = str -> str.startsWith("J"); Predicate predicate2 = str -> str.length() < 4; List result = names.stream() .filter(predicate1.or(predicate2.negate())) .collect(Collectors.toList()); assertEquals(3, result.size()); assertThat(result, contains("Adam","Alexander","John")); }

Hier haben wir eine Kombination aus oder () und negate () verwendet , um die Liste nach Namen zu filtern, die mit „J“ beginnen oder eine Länge von nicht weniger als 4 haben.

5.4. Kombinieren Sie Prädikate Inline

Wir müssen unsere Prädikate nicht explizit definieren , um und () oder () und negate () zu verwenden.

Wir können sie auch inline verwenden, indem wir das Prädikat wirken :

@Test public void whenFilterListWithCombinedPredicatesInline_thenSuccess(){ List result = names.stream() .filter(((Predicate)name -> name.startsWith("A")) .and(name -> name.length()<5)) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }

6. Kombinieren einer Sammlung von Prädikaten

Schließlich wollen wir sehen , wie man Kette eine Sammlung von Prädikaten durch sie zu reduzieren.

Im folgenden Beispiel haben wir eine Liste von Prädikaten , die wir mit Predicate.and () kombiniert haben :

@Test public void whenFilterListWithCollectionOfPredicatesUsingAnd_thenSuccess(){ List
    
      allPredicates = new ArrayList
     
      (); allPredicates.add(str -> str.startsWith("A")); allPredicates.add(str -> str.contains("d")); allPredicates.add(str -> str.length() > 4); List result = names.stream() .filter(allPredicates.stream().reduce(x->true, Predicate::and)) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Alexander")); }
     
    

Beachten Sie, dass wir unsere Basisidentität verwenden als:

x->true

Das wird jedoch anders sein, wenn wir sie mit Predicate.or () kombinieren möchten :

@Test public void whenFilterListWithCollectionOfPredicatesUsingOr_thenSuccess(){ List result = names.stream() .filter(allPredicates.stream().reduce(x->false, Predicate::or)) .collect(Collectors.toList()); assertEquals(2, result.size()); assertThat(result, contains("Adam","Alexander")); }

7. Fazit

In diesem Artikel haben wir verschiedene Möglichkeiten zum Verketten von Prädikaten in Java 8 untersucht, indem wir filter () verwendet, komplexe Prädikate erstellt und Prädikate kombiniert haben .

Der vollständige Quellcode ist auf GitHub verfügbar.