Java 8謂詞鏈

1.概述

在本快速教程中,我們將討論在Java 8中鏈接Predicates不同方法。

2.基本示例

首先,**讓我們看看如何使用簡單的Predicate**來過濾名稱List

@Test

 public void whenFilterList_thenSuccess(){

 List<String> names = Arrays.asList("Adam", "Alexander", "John", "Tom");

 List<String> result = names.stream()

 .filter(name -> name.startsWith("A"))

 .collect(Collectors.toList());



 assertEquals(2, result.size());

 assertThat(result, contains("Adam","Alexander"));

 }

在此示例中,我們使用Predicate過濾了名稱List ,以僅保留以“ A”開頭的名稱:

name -> name.startsWith("A")

但是,如果我們想應用多個Predicates怎麼辦?

3.多個過濾器

如果我們要應用多個Predicates一種選擇是簡單地鏈接多個過濾器:

@Test

 public void whenFilterListWithMultipleFilters_thenSuccess(){

 List<String> result = names.stream()

 .filter(name -> name.startsWith("A"))

 .filter(name -> name.length() < 5)

 .collect(Collectors.toList());



 assertEquals(1, result.size());

 assertThat(result, contains("Adam"));

 }

現在,我們更新了示例,以通過提取以“ A”開頭且長度小於5的名稱來過濾列表。

我們使用了兩個過濾器-每個Predicate

4.複合Predicate

現在,我們可以使用具有復雜Predicate一個過濾器,而不是使用多個過濾器

@Test

 public void whenFilterListWithComplexPredicate_thenSuccess(){

 List<String> result = names.stream()

 .filter(name -> name.startsWith("A") && name.length() < 5)

 .collect(Collectors.toList());



 assertEquals(1, result.size());

 assertThat(result, contains("Adam"));

 }

此選項比第一個選項更靈活,因為**我們可以使用按位運算來構建所需的Predicate**使其盡可能複雜。

5.組合Predicates

接下來,如果我們不想使用按位運算來構建複雜的Predicate ,則Java 8 Predicate具有有用的方法,可用於組合Predicates

我們將使用Predicate.and()Predicate.or()Predicate.negate().方法組合Predicates Predicate.negate().

5.1。 Predicate.and()

在此示例中,我們將明確定義Predicates ,然後使用Predicate.and():將它們組合Predicate.and():

@Test

 public void whenFilterListWithCombinedPredicatesUsingAnd_thenSuccess(){

 Predicate<String> predicate1 = str -> str.startsWith("A");

 Predicate<String> predicate2 = str -> str.length() < 5;



 List<String> result = names.stream()

 .filter(predicate1.and(predicate2))

 .collect(Collectors.toList());



 assertEquals(1, result.size());

 assertThat(result, contains("Adam"));

 }

如我們所見,語法非常直觀,方法名稱建議操作的類型。使用and() ,我們通過僅提取同時滿足兩個條件的名稱來過濾List

5.2。 Predicate.or()

我們還可以使用Predicate.or()組合Predicates.

讓我們提取以“ J”開頭的名稱以及長度小於4的名稱:

@Test

 public void whenFilterListWithCombinedPredicatesUsingOr_thenSuccess(){

 Predicate<String> predicate1 = str -> str.startsWith("J");

 Predicate<String> predicate2 = str -> str.length() < 4;



 List<String> result = names.stream()

 .filter(predicate1.or(predicate2))

 .collect(Collectors.toList());



 assertEquals(2, result.size());

 assertThat(result, contains("John","Tom"));

 }

5.3。 Predicate.negate()

當結合我們的Predicates時,我們可以使用Predicate.negate()

@Test

 public void whenFilterListWithCombinedPredicatesUsingOrAndNegate_thenSuccess(){

 Predicate<String> predicate1 = str -> str.startsWith("J");

 Predicate<String> predicate2 = str -> str.length() < 4;



 List<String> result = names.stream()

 .filter(predicate1.or(predicate2.negate()))

 .collect(Collectors.toList());



 assertEquals(3, result.size());

 assertThat(result, contains("Adam","Alexander","John"));

 }

在這裡,我們使用or()negate()來按以“ J”開頭或長度不少於4的名稱過濾List

5.4。內聯合併Predicates

我們不需要顯式定義Predicates來使用and(), or()negate().

我們還可以通過強制轉換Predicate來內聯使用它們:

@Test

 public void whenFilterListWithCombinedPredicatesInline_thenSuccess(){

 List<String> result = names.stream()

 .filter(((Predicate<String>)name -> name.startsWith("A"))

 .and(name -> name.length()<5))

 .collect(Collectors.toList());



 assertEquals(1, result.size());

 assertThat(result, contains("Adam"));

 }

6.組合Predicates集合

最後,讓我們看看如何通過減少Predicates來鏈接Predicates集合。

在下面的示例中,我們使用Predicate.and()合併了一個Predicates List

@Test

 public void whenFilterListWithCollectionOfPredicatesUsingAnd_thenSuccess(){

 List<Predicate<String>> allPredicates = new ArrayList<Predicate<String>>();

 allPredicates.add(str -> str.startsWith("A"));

 allPredicates.add(str -> str.contains("d"));

 allPredicates.add(str -> str.length() > 4);



 List<String> result = names.stream()

 .filter(allPredicates.stream().reduce(x->true, Predicate::and))

 .collect(Collectors.toList());



 assertEquals(1, result.size());

 assertThat(result, contains("Alexander"));

 }

請注意,我們將基本身份用作:

x->true

但是,如果我們想使用Predicate.or()將它們組合起來,那將是不同的:

@Test

 public void whenFilterListWithCollectionOfPredicatesUsingOr_thenSuccess(){

 List<String> result = names.stream()

 .filter(allPredicates.stream().reduce(x->false, Predicate::or))

 .collect(Collectors.toList());



 assertEquals(2, result.size());

 assertThat(result, contains("Adam","Alexander"));

 }

7.結論

在本文中,我們通過使用filter(),構建複雜的Predicates以及組合Predicates. ,探索了Java 8中鏈接謂詞的不同方法Predicates.

完整的源代碼可在GitHub上獲得