Java 8的用法(泛型接口,谓词链)
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的不同方法):
首先,让我们看看如何使用简单的谓词来过滤名称列表:
@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")
但是,如果我们想要应用多个Predicates呢?
3.多个过滤器
如果我们想要应用多个谓词,一个选项是简单地链接多个过滤器:@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的名称来过滤我们的列表,我们使用了两种过滤修饰-每个谓词。
4.复杂的谓词
现在,我们可以使用一个带有复杂Predicate的过滤器,而不是使用多个过滤器:
@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"));
}
这个选项比第一个选项更灵活,因为我们可以使用按位运算来构建 我们想要的复杂谓词。
5.结合谓词
接下来,如果我们不想使用按位运算构建复杂的谓词,Java 8 Predicate可以使用有用的方法来组合谓词我们将使用Predicate.and(),Predicate.or()和Predicate.negate()方法组合谓词。
5.1 Predicate.and()
在这个例子中,我们将明确定义我们的谓词,然后我们将使用Predicate.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"));
}
我们可以看到,语法非常直观,方法名称表明了操作的类型。使用Predicate.and(),我们通过仅提取满足两个条件的名称来过滤我们的列表。
5.2 Predicate.or()
我们也可以使用 Predicate.or()来组合Predicates。 让我们提取名称以“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"));
}
5.3 Predicate.negate()
在组合我们的Predicates时我们也可以使用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 来过滤List
5.4 结合谓词内联
我们不需要明确定义要使用的谓词and(), or(),以及negate()。 我们也可以通过强制谓词来内联它们:
@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"));
}
6.结合一组谓词
最后,让我们看看如何通过减少它们来链接一组Predicates。在下面的例子中,我们有一个列表的谓词,我们使用组合Predicate.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
但是如果我们想要使用Predicate.or()组合它们会有所不同:
@Test
public 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"));
}
Java 8的用法(泛型接口,谓词链)的更多相关文章
- Java安全之挖掘回显链
Java安全之挖掘回显链 0x00 前言 前文中叙述反序列化回显只是为了拿到Request和Response对象.在这里说的的回显链其实就是通过一连串反射代码获取到该Request对象. 在此之前想吹 ...
- JAVA的continue用法
JAVA的continue用法: public class test{ public static void main(String [] args){ for(int i=0;i<=10;i ...
- Java Spring AOP用法
Java Spring AOP用法 Spring AOP Java web 环境搭建 Java web 项目搭建 Java Spring IOC用法 spring提供了两个核心功能,一个是IoC(控制 ...
- Java Spring IOC用法
Java Spring IOC用法 Spring IoC 在前两篇文章中,我们讲了java web环境搭建 和 java web项目搭建,现在看下spring ioc在java中的运用,开发工具为In ...
- 四种Java线程池用法解析
本文为大家分析四种Java线程池用法,供大家参考,具体内容如下 http://www.jb51.net/article/81843.htm 1.new Thread的弊端 执行一个异步任务你还只是如下 ...
- JAVA中ArrayList用法
JAVA中ArrayList用法 2011-07-20 15:02:03| 分类: 计算机专业 | 标签:java arraylist用法 |举报|字号 订阅 Java学习过程中做题时 ...
- this在java中的用法
this在java中的用法 1.使用this关键字引用成员变量 作用:解决成员变量与参数或局部变量命名冲突的问题 public class Dog { String name; public Dog( ...
- java assert的用法简介【转】
assert的基本用法 assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制,如C,C++和Eiffel等,但是支持的形式不尽相同,有的是通过语言本身.有的是通过库 ...
- lodash用法系列(5),链式
Lodash用来操作对象和集合,比Underscore拥有更多的功能和更好的性能. 官网:https://lodash.com/引用:<script src="//cdnjs.clou ...
随机推荐
- python+matplotlib+绘制不同图标类型
#==================================================================#首先需要导入两个文件import matplotlib.pypl ...
- TortoiseGit的ssh key和Git的ssh key
情景模拟: 你使用Git+TortoiseGit对项目进行版本控制,本地库(自己电脑建立的.git)与远程库(如GitLab上建立)通信需要使用ssh验证,你用git生成公钥并保存到了Gitlab上, ...
- 查看mac系统版本
打开终端, 输入命令 uname -a 回车 x86_64 表示系统为64位 i686 表示系统32位的
- VS2017无法发现单元测试,不能运行单元测试的解决方案
问题: 在VS2017中新建空的单元测试后,无法运行测试,即右键菜单的"运行测试"和"调试测试" 不能运行,在测试资源管理中也无法列出这个测试. 解决方案: 1 ...
- [NodeJs Windows编译学习]
https://blog.csdn.net/gesturexiaoxin/article/details/80162944
- SQL Server查询重复数据
1.查询单列重复: select * from test where name in (select name from test group by name having count (name) ...
- docker images
docker images 介绍 镜像是动态的容器的静态表示,包括容器所要运行的应用代码以及运行时的配置.Docker镜像包括一个或者多个只读层(read-only layers),因此,镜像一旦被创 ...
- 兼容IE8,滚动加载下一页
// 滚动加载下一页 var nowScrolledHeight = document.documentElement.scrollTop || document.body.scrol ...
- unittest中的Empty suite错误
import unittest from selenium import webdriver class ibdata(unittest.TestCase): @classmethod def set ...
- Razor Page Library:开发独立通用RPL(内嵌wwwroot资源文件夹)
ASP.NET Core知多少系列:总体介绍及目录 Demo路径:GitHub-RPL.Demo 1. Introduction Razor Page Library 是ASP.NET Core 2. ...