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”开头的名称:

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

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

3.多个过滤器

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

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

}

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

  1. 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的用法(泛型接口,谓词链)的更多相关文章

  1. Java安全之挖掘回显链

    Java安全之挖掘回显链 0x00 前言 前文中叙述反序列化回显只是为了拿到Request和Response对象.在这里说的的回显链其实就是通过一连串反射代码获取到该Request对象. 在此之前想吹 ...

  2. JAVA的continue用法

    JAVA的continue用法: public class test{ public static void main(String [] args){  for(int i=0;i<=10;i ...

  3. Java Spring AOP用法

    Java Spring AOP用法 Spring AOP Java web 环境搭建 Java web 项目搭建 Java Spring IOC用法 spring提供了两个核心功能,一个是IoC(控制 ...

  4. Java Spring IOC用法

    Java Spring IOC用法 Spring IoC 在前两篇文章中,我们讲了java web环境搭建 和 java web项目搭建,现在看下spring ioc在java中的运用,开发工具为In ...

  5. 四种Java线程池用法解析

    本文为大家分析四种Java线程池用法,供大家参考,具体内容如下 http://www.jb51.net/article/81843.htm 1.new Thread的弊端 执行一个异步任务你还只是如下 ...

  6. JAVA中ArrayList用法

    JAVA中ArrayList用法 2011-07-20 15:02:03|  分类: 计算机专业 |  标签:java  arraylist用法  |举报|字号 订阅     Java学习过程中做题时 ...

  7. this在java中的用法

    this在java中的用法 1.使用this关键字引用成员变量 作用:解决成员变量与参数或局部变量命名冲突的问题 public class Dog { String name; public Dog( ...

  8. java assert的用法简介【转】

    assert的基本用法 assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制,如C,C++和Eiffel等,但是支持的形式不尽相同,有的是通过语言本身.有的是通过库 ...

  9. lodash用法系列(5),链式

    Lodash用来操作对象和集合,比Underscore拥有更多的功能和更好的性能. 官网:https://lodash.com/引用:<script src="//cdnjs.clou ...

随机推荐

  1. 转载 CSDN 谈谈我对证券公司一些部门的理解(前、中、后台)

    谈谈我对证券公司一些部门的理解(前.中.后台) 2018年02月08日 15:11:07 unirong 阅读数:2165   文中对各大部门的分析都是从作者多年经历总结出来的有感之谈,尤其是前台的6 ...

  2. java.lang.ClassCastException: net.sf.json.JSONNull cannot be cast to net.sf.json.JSONObject的解决方法

    报错情况已经说明了,在百度查了好几个解决方法,这里总结一下: 首先:加一个判断是否为空,再做操作 // 得到json串 String jsonString = UtilPOSTGET.UPost(FO ...

  3. 面试题:int和Integer的区别

    java底层源码:  -128  127之间

  4. Server的API如何设计才满足RESTful要求?

    Server的API如何设计才满足RESTful要求? 首先是简洁版里面的那几点.外加一些附带的 best practices:1. URL root: https://example.org/api ...

  5. vue - 新建一个项目

    首先: 要先安装node 及 npm Node.js官方安装包及源码下载地址:http://nodejs.org/ 双击安装,在安装界面一直Next 直到Finish完成安装. 打开控制命令行程序(C ...

  6. group by 多个字段

    众所周知,group by 一个字段是根据这个字段进行分组,那么group by 多个字段的结果是什么呢?由前面的结论类比可以得到,group by 后跟多个子段就是根据多个字段进行分组 注:下面的例 ...

  7. CPU运行原理

    问题: CPU位宽表示什么意思? 下面这个是 https://www.bilibili.com/video/av9667986?from=search&seid=336127932106862 ...

  8. 问题:win7下配置好服务器就是不能查询数据库。(已解决)

    我用C写访问mysql的CGI程序,可以执行. 但是,当我写好网页再去访问这个CGI,出现下面的错误 我的环境是:IIS作为服务器,MYSQL数据库,VC++6.0写CGI. 跟踪了一下,发现只要我调 ...

  9. 使用 TRESTClient 与 TRESTRequest 作为 HTTP Client

    在 Delphi XE 推出以前的年代,Delphi的发展方向是笔直朝向资料库连结Windows 应用程式这个目标不断前进的,从Delphi 1开始,到Delphi 7,Delphi奠定了VB Kil ...

  10. ABP入门系列(2)——领域层创建实体

    ABP入门系列目录--学习Abp框架之实操演练 这一节我们主要和领域层打交道.首先我们要对ABP的体系结构以及从模板创建的解决方案进行一一对应.网上有代码生成器去简化我们这一步的任务,但是不建议初学者 ...