Java 8 谓词(Predicate)链

Java 8 谓词(Predicate)链

本文介绍多种方式实现谓词链接。

1. 从示例开始

我们先从一个简单示例开始,如何实用简单谓词过滤集合:

@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"));
}

上面示例过滤名称列表,仅保留以字母A开头的名称:

name -> name.startsWith("A")

那么如何实现多个谓词组合条件过滤?

2. 多条件过滤

2.1 直接链接调用

最简单方法时直接链接调用:

@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的名称,我们实用两个filter,每个过滤实用谓词作为条件。

2.2 复杂的谓词

我们可以修改上节示例,使用单个带复杂谓词参数的过滤器:

@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"));
}

这种方式更灵活,可以使用位操作符构建复杂的谓词逻辑。

3. 组合谓词

如果我们不想使用位操作符构建复杂的谓词条件,Java 8 Predicate提供了有用的方法可以组合谓词。常用的方法包括Predicate.and(), Predicate.or(), and Predicate.negate()

3.1 Predicate.and()

下面示例首先定义两个谓词,然后使用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(),我们实现了对列表过滤,仅返回满足两个条件的名称。

3.2 Predicate.or()

我们也可以使用or方法组合谓词,下面示例同时返回以字母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"));
}

3.3 Predicate.negate()

还有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的名称集合。

3.4 通过lambda表达式组合谓词

我们并不需要显示定义谓词才能组合,可以直接通过lambda表达式实现:

@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"));
}

3.5 组合谓词集合

最后我们看看如何链接谓词集合。下面示例中定义了谓词集合,然后通过reduce方法进行组合,符合条件使用and进行链接:

@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

但如果使用or()方法将它们组合在一起,情况就不同了:

@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"));

}

4. 总结

本文我们介绍了Java 8 中不同方式实现多谓词组合过滤,可以在filter方法中使用复杂谓词或组合谓词。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值