从零单排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的使用方法,已经针对的场景。

相关文章
相关标签/搜索