Java 8流 - 过滤多个条件

21

根据一些体育赛事数据,我有一个Fixture对象,其中有getHome()getAway()方法。我想缩短我编写的此方法,仅使用单个lambda函数(而不是创建新列表和两个lambda函数),这是可能的吗?

    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;
}
5个回答

19

足够简单

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

编辑:假设顺序对你不重要。如果你的最终列表需要先显示主场结果,然后是客场结果,请查看Elliott Frisch的答案


14

如果您想用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)); 
...

4
假设顺序无关紧要,你可以在一行中完成。比如说,
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;
}

3
你可以简单地创建条件拼接,也可以拼接多个筛选器调用。

条件拼接

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

多重过滤器调用

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

每个下一个过滤器调用都适用于已过滤的结果。作者很可能想要使用OR过滤条件。 - undefined

2
你可以做以下事情。
someStream.filter(((Predicate<SomeClass>) someObject-> someCondition).or(someObject-> someOtherCondition))

或者您可以定义自己的“or”函数,这样就不会引起如此深的层次结构。
@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;
      }
 ))

2
这是一个隐藏在页面底部的宝石!希望更多的开发者意识到这些解决方案的优雅。 - ATutorMe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接