zoukankan      html  css  js  c++  java
  • 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”开头的名称:

    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"));
    
    }
  • 相关阅读:
    PJzhang:CVE-2020-1472微软NetLogon权限提升漏洞~复现
    PJzhang:vulnhub靶机sunset系列SUNSET:DECOY
    PJzhang:vulnhub靶机sunset系列SUNSET:TWILIGHT
    PJzhang:vulnhub靶机sunset系列SUNSET:SUNRISE
    PJzhang:vulnhub靶机sunset系列SUNSET:MIDNIGHT
    PJzhang:vulnhub靶机sunset系列SUNSET:SOLSTICE
    PJzhang:whatweb指纹扫描工具样例
    HTTP状态码解读
    【并发】线程与进程的区别
    MYSQL之性能优化 ----MySQL性能优化必备25条
  • 原文地址:https://www.cnblogs.com/jay-wu/p/10190082.html
Copyright © 2011-2022 走看看