首页 技术 正文
技术 2022年11月15日
0 收藏 316 点赞 3,939 浏览 5383 个字

1.泛型接口

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

Specification接口为:
public interface Specification<T> {
Predicate toPredicate(Root<T> var1, CriteriaQuery<?> var2, CriteriaBuilder var3);
}

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

   public static Specification<AlarmLog> searchKeyword(final String key, final Date startTime, final Date endTime) {
return new Specification<AlarmLog>() {
@Override
public Predicate toPredicate(Root<AlarmLog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (StringUtils.isNotEmpty(key)) {
predicates.add(criteriaBuilder.or(
criteriaBuilder.like(root.<String>get("description"), "%" + key + "%"),
criteriaBuilder.like(root.<String>get("exceptionMessage"), "%" + key + "%")));
}
if (startTime != null && endTime != null){
predicates.add(criteriaBuilder.and(
criteriaBuilder.greaterThan(root.<Date>get("createTime"), startTime),
criteriaBuilder.lessThan(root.<Date>get("createTime"), endTime)
));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[]{}));
}
};
}

1.8以后的写法为:

 public static Specification<RecorderTask> searchKeyword(final String key, final Boolean isDeleted) {
return (root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
if (StringUtils.isNotEmpty(key)) {
predicates.add(criteriaBuilder.or(
criteriaBuilder.like(root.<String>get("fileName"), "%" + key + "%"),
criteriaBuilder.like(root.<String>get("outputPath"), "%" + key + "%")));
} if (isDeleted != null) {
predicates.add(criteriaBuilder.or(
criteriaBuilder.equal(root.<Boolean>get("isDeleted"), isDeleted)));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[]{}));
};
}

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

首先,让我们看看如何使用简单的谓词来过滤名称列表:
@Testpublic 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”开头的名称:

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

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

3.多个过滤器

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

  2. @Testpublic 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的名称来过滤我们的列表,我们使用了两种过滤修饰-每个谓词。

4.复杂的谓词

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

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

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

5.结合谓词

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

5.1 Predicate.and()

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

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

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

5.2 Predicate.or()

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

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

@Testpublic 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 结合谓词内联

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

@Testpublic 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。在下面的例子中,我们有一个列表的谓词,我们使用组合Predicate.and():

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

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

  1. x->true

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

@Testpublic 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"));}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,490
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,905
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,738
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,491
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,129
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,292