從零單排Java 8(1) —— Predicate使用介紹

簡介

image.png

在接下來的階段中,將和你們分享Java 8 系列的一些知識點。本文和你們講述Predicate的使用方法介紹以及其背景。bash

簡單示例

首先,讓咱們看看如何使用簡單的filter()來過濾一個List集合:spa

@Test
public void whenFilterList(){
   List<String> names = Arrays.asList("Apps", "Alibaba", "william", "Son");
   List<String> result = names.stream()
     .filter(name -> name.startsWith("A"))
     .collect(Collectors.toList());
    
   assertEquals(2, result.size());
   assertThat(result, contains("Apps","Alibaba"));
}
複製代碼

在此示例中,咱們過濾了List集合,保留以「A」開頭的數據 :code

name -> name.startsWith("A")
複製代碼

可是假如須要過濾多個條件的話,應該如何?cdn

多個過濾條件

若是咱們想要應用多個過濾,一個比較簡單地方式就是設置多個過濾器:blog

@Test
public void whenFilterListWithMultiple(){
    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("Apps"));
}

複製代碼

看上面的示例,經過提取以「A」開頭而且長度小於5的數據來過濾咱們的集合。ip

咱們使用了兩個過濾條件。string

改進版本

如今,咱們能夠使用一個帶有複雜的過濾器,而不是使用多個過濾器filer()it

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

這個改進比第一個更靈活,由於咱們能夠使用按位運算來構建咱們想要的複雜語句。io

組合Predicates

接下來,若是咱們不想使用按位運算構建複雜語句,Java 8 Predicate能夠使用有用的方法來組合過濾條件。function

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

Predicate.and()

咱們來看看只用 and()的方式,能夠怎麼用

@Test
public void whenFilterListWithCombinedPredicatesUsingAnd(){
    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。

Predicate.or()

接下來,咱們看看or()的方式使用。條件爲w開頭、或者長度小於4

@Test
public void whenFilterListWithCombinedPredicatesUsingOr(){
    Predicate<String> predicate1 =  str -> str.startsWith("w");
    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"));
}

複製代碼

Predicate.negate()

如今咱們來結合一下看看 negate()的使用場景,這個方法是指相反條件,即 <>!xxx

@Test
public void whenFilterListWithCombinedPredicatesUsingOrAndNegate(){
    Predicate<String> predicate1 =  str -> str.startsWith("w");
    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("Apps","Alibaba","william"));
}

複製代碼

上示例的代碼中,條件是爲 w開頭的或者 數據的長度不是小於4的過濾條件。

predicate新寫法

咱們甚至也能夠不用寫 and()、or()、negate()就能夠使用predicate方法:

@Test
public void whenFilterListWithCombinedPredicatesInline(){
    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("Apps"));
}
複製代碼

複雜的條件組合

最後,讓咱們看看如何經過編寫出一個能夠支持多個複雜條件的過濾方法。

在下面的例子中,咱們有一個列表集合,咱們使用組合Predicate.and() :

@Test
public void whenFilterListWithCollectionOfPredicatesUsingAnd(){
    List<Predicate<String>> allPredicates = new ArrayList<Predicate<String>>();
    allPredicates.add(str -> str.startsWith("A"));
    allPredicates.add(str -> str.contains("ba"));        
    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("Alibaba"));
}

複製代碼

請留意,咱們使用了一個關鍵性代碼:

x->true
複製代碼

可是若是咱們想要使用Predicate.or()組合它們會有所不一樣:

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

複製代碼

結論

本文主要是講解了如何更好的過濾List中的數據,filter()Predicates的使用方法,已經針對的場景。

相關文章
相關標籤/搜索