【问题标题】:Java 8 Streams - Filter More Than One ConditionJava 8 Streams - 过滤多个条件
【发布时间】:2018-08-28 07:52:59
【问题描述】:

根据一些运动结果数据,我有一个Fixture 对象,它有getHome()getAway() 方法。我想缩短我写的这个方法,只使用一个 lambda 函数(而不是创建一个新列表和两个 lambdas),这可能吗?

    private Collection<FixtureResult> finalResults(Team team) {

    List<FixtureResult>finalResults = new ArrayList<>();

    List<FixtureResult> homeResults = resultList.stream().filter(fixture ->
            fixture.getHome().equals(team))
            .collect(toList());

    List<FixtureResult> awayResults = resultList.stream().filter(fixture ->
            fixture.getAway().equals(team))
            .collect(toList());

    finalResults.addAll(homeResults);
    finalResults.addAll(awayResults);

    return finalResults;
}

【问题讨论】:

    标签: java lambda java-8 java-stream


    【解决方案1】:

    如果你想看中 lambda:

    Predicate<FixtureResult> isHome = fr -> fr.getHome().equals(team)
    Predicate<FixtureResult> isAway = fr -> fr.getAway().equals(team)
    
    resultList.stream()
      .filter(isHome.or(isAway))
      .collect(toList()));
    

    您甚至可以提取 compose 谓词以单独测试它,而不涉及流,这对于更复杂的谓词很有用:

    Predicate<FixtureResult> isHomeOrAway = isHome.or(isAway)
    
    assertTrue(isHomeOrAway(homeFixture)); 
    ...
    

    【讨论】:

      【解决方案2】:

      您可以执行以下操作

      someStream.filter(((Predicate<SomeClass>) someObject-> someCondition).or(someObject-> someOtherCondition))
      

      或者您可以定义自己的“或”函数,不会导致如此深的层次结构

      @SuppressWarnings("unchecked")
      <R> Predicate<R> or(Predicate<R> ...predicates) {
         return r -> Arrays.stream(predicates).anyMatch(p -> p.test(r));
      }
      

      这为您提供了一个更干净的界面,无需强制转换和嵌套

      .filter(or(
            yourObject -> {
                return false;
            },
            yourObject -> {
                return false;
            },
            yourObject -> {
                return false;
            },
            yourObject -> {
                return false;
            }
       ))
      

      【讨论】:

        【解决方案3】:

        您可以简单地创建条件连接或可以连接多个过滤器调用

        条件串联

        myList.stream()
              .filter(element -> (condition1 && condition2 && condition3))
        

        多重过滤调用

        myList.stream()
              .filter(element -> condition1)
              .filter(element -> condition2)
              .filter(element -> condition3)
        

        【讨论】:

          【解决方案4】:

          够简单

          resultList.stream()
                  .filter(fixture -> fixture.getHome().equals(team) || fixture.getAway().equals(team)))
                  .collect(toList());
          

          编辑:这是假设顺序对您无关紧要。如果您的最终名单需要有主场结果然后离开,请查看Elliott Frisch's answer

          【讨论】:

            【解决方案5】:

            假设顺序无关紧要,您可以在一行中完成。喜欢,

            private Collection<FixtureResult> finalResults(Team team) {
                return resultList.stream()
                        .filter(fixture -> fixture.getHome().equals(team) 
                                || fixture.getAway().equals(team))
                        .collect(toList());
            }
            

            如果订单很重要(主场结果然后离开),您可以用一个 List 点赞来完成

            private Collection<FixtureResult> finalResults(Team team) {
                List<FixtureResult> al = new ArrayList<>(resultList.stream()
                        .filter(fixture -> fixture.getHome().equals(team)).collect(toList()));
                al.addAll(resultList.stream()
                        .filter(fixture -> fixture.getAway().equals(team)).collect(toList()));
                return al;
            }
            

            【讨论】:

              猜你喜欢
              • 2014-07-26
              • 1970-01-01
              • 2018-01-01
              • 2016-02-22
              • 2022-12-05
              • 2022-01-18
              相关资源
              最近更新 更多