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. HFS 轻量化 的文件服务器

    国外的工具 国内的工具

  2. Bootstrap 常用属性

    一,关于按钮 btn系列 二.关于div 移动位置 col 系列 col-md 系列 col-lg系列 这些都是让多个div在当前页面等大小 三.居中系列 1.文本居中 text-center 2.图 ...

  3. SpringAop注解实现日志的存储

    一.介绍 1.AOP的作用 在OOP中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加.AOP则将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封 ...

  4. 手机touch事件及参数【转】(自己懒得写了,找了一篇摘过来)

    [html5构建触屏网站]之touch事件 前言 一个触屏网站到底和传统的pc端网站有什么区别呢,交互方式的改变首当其冲.例如我们常用的click事件,在触屏设备下是如此无力. 手机上的大部分交互都是 ...

  5. Edge-assisted Traffic Engineering and applications in the IoT

    物联网中边缘辅助的流量工程和应用 本文为SIGCOMM 2018 Workshop (Mobile Edge Communications, MECOMM)论文. 笔者翻译了该论文.由于时间仓促,且笔 ...

  6. 【XSS】利用 onload 事件监控流量劫持

    说到跨站资源监控,首先会联想到『Content Security Policy』.既然 CSP 好用,我们何必自己再搞一套呢.那就先来吐槽下 CSP 的缺陷. 目前的 CSP 日志不详细 用过 CSP ...

  7. 如何用VSCode调试Vue.js

    VS Code相关插件:Chinese (Simplified) Language Pack for Visual Studio Code Debugger for Chrome ESLint Vet ...

  8. C++ Opencv remap()重映射函数详解及使用示例

    一.重映射及remap()函数介绍 重映射,就是把一幅图像中某位置的像素放置到另一图像指定位置的过程.即: 在重映射过程中,图像的大小也可以同时发生改变.此时像素与像素之间的关系就不是一一对应关系,因 ...

  9. [Swift]LeetCode218. 天际线问题 | The Skyline Problem

    A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...

  10. [Swift]LeetCode287. 寻找重复数 | Find the Duplicate Number

    Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...