java 谓词_Java 8的用法(泛型接口,谓词链)

1.泛型接口

我们举个例子,以前来看一下JPA定义的写法:

Specification接口为:

public interface Specification{

Predicate toPredicate(Root var1, CriteriaQuery>var2, CriteriaBuilder var3);

}

以前的写法为(定义一个静态内部类实现):

public static Specification searchKeyword(final String key, final Date startTime, finalDate endTime) {return new Specification() {

@Overridepublic Predicate toPredicate(Root root, CriteriaQuery>criteriaQuery, CriteriaBuilder criteriaBuilder) {

List predicates = new ArrayList();if(StringUtils.isNotEmpty(key)) {

predicates.add(criteriaBuilder.or(

criteriaBuilder.like(root.get("description"), "%" + key + "%"),

criteriaBuilder.like(root.get("exceptionMessage"), "%" + key + "%")));

}if (startTime != null && endTime != null){

predicates.add(criteriaBuilder.and(

criteriaBuilder.greaterThan(root.get("createTime"), startTime),

criteriaBuilder.lessThan(root.get("createTime"), endTime)

));

}return criteriaBuilder.and(predicates.toArray(newPredicate[]{}));

}

};

}

1.8以后的写法为:

public static Specification searchKeyword(final String key, finalBoolean isDeleted) {return (root, criteriaQuery, criteriaBuilder) ->{

List predicates = new ArrayList<>();if(StringUtils.isNotEmpty(key)) {

predicates.add(criteriaBuilder.or(

criteriaBuilder.like(root.get("fileName"), "%" + key + "%"),

criteriaBuilder.like(root.get("outputPath"), "%" + key + "%")));

}if (isDeleted != null) {

predicates.add(criteriaBuilder.or(

criteriaBuilder.equal(root.get("isDeleted"), isDeleted)));

}return criteriaBuilder.and(predicates.toArray(newPredicate[]{}));

};

}

2.谓词链(讨论在Java 8中链接Predicates的不同方法):

首先,让我们看看如何使用简单的谓词来过滤名称列表:

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

}

在这个例子中,我们过滤了名称列表,只使用谓词保留以“A”开头的名称:

name ->name.startsWith("A")

但是,如果我们想要应用多个Predicates呢?

3.多个过滤器

如果我们想要应用多个谓词,一个选项是简单地链接多个过滤器:

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

}

我们现在更新了我们的示例,通过提取以“A”开头并且长度小于5的名称来过滤我们的列表,我们使用了两种过滤修饰-每个谓词。

4.复杂的谓词

现在,我们可以使用一个带有复杂Predicate的过滤器,而不是使用多个过滤器:

@Testpublic voidwhenFilterListWithComplexPredicate_thenSuccess(){

List result =names.stream()

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

.collect(Collectors.toList());

assertEquals(1, result.size());

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

}

这个选项比第一个选项更灵活,因为我们可以使用按位运算来构建 我们想要的复杂谓词。

5.结合谓词

接下来,如果我们不想使用按位运算构建复杂的谓词,Java 8 Predicate可以使用有用的方法来组合谓词我们将使用Predicate.and(),Predicate.or()和Predicate.negate()方法组合谓词。

5.1 Predicate.and()

在这个例子中,我们将明确定义我们的谓词,然后我们将使用Predicate.and()组合它们:

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

}

我们可以看到,语法非常直观,方法名称表明了操作的类型。使用Predicate.and(),我们通过仅提取满足两个条件的名称来过滤我们的列表。

5.2 Predicate.or()

我们也可以使用 Predicate.or()来组合Predicates。 让我们提取名称以“J”开头,以及长度小于4的名称:

@Testpublic voidwhenFilterListWithCombinedPredicatesUsingOr_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()

在组合我们的Predicates时我们也可以使用Predicate.negate():

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

}

在这里,我们使用or()和negate()的组合来按名称以“J”开头或长度不小于4 来过滤List

5.4 结合谓词内联

我们不需要明确定义要使用的谓词and(), or(),以及negate()。 我们也可以通过强制谓词来内联它们:

@Testpublic voidwhenFilterListWithCombinedPredicatesInline_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.结合一组谓词

最后,让我们看看如何通过减少它们来链接一组Predicates。在下面的例子中,我们有一个列表的谓词,我们使用组合Predicate.and():

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

}

注意,我们使用基本标识作为:

x->true

但是如果我们想要使用Predicate.or()组合它们会有所不同:

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

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值