【问题标题】:Java Stream filtering on same fields but different criteriaJava Stream过滤相同的字段但不同的标准
【发布时间】:2020-03-06 01:27:11
【问题描述】:

我有一个 Person 类:

@Data
public class Person {
   private Integer id;
   private String status;
}

我有一个名为 personList 的人员列表:

[{ 
    "id": null,
    "status": "inactive"
 },
 { 
    "id": 2,
    "status": "inactive"
 },
 { 
    "id": null,
    "status": "active"
 }]

现在我需要找到所有状态为“非活动”的人,无论此人是否有 ID。如果某人没有 ID,但状态为“活动”,则也包括该人。我正在使用 Java 流进行过滤:

 List<Person> inactivePersonList = 
     personList.stream()
               .filter(person -> person.getStatus().equals("inactive"))
               .filter(person -> person.getId() == null && person.getStatus().equals("active"))
               .collect(Collectors.toList());

直播后的结果是没人接。第一个人没有被接走是因为它没有通过第二道过滤器,最后一个人没有被捡到是因为它没有通过第一道过滤器。

我想我可以通过使用OR 将两个过滤器合并为一个来修复它,但我试图让每个过滤器都变得简单,所以在进行更改之前,我想问一下是否有更好的方法做。谢谢。

【问题讨论】:

  • 使用一个过滤器,但创建一种方法来过滤掉两者的“非活动”用户。并使用enum。
  • 当您已经知道在另一个 filter 中使用 &amp;&amp; 时,我没有明显错过在过滤器中使用 || 的条件,而这并不是真正需要的。

标签: java java-8 java-stream


【解决方案1】:

过滤器是相加的。他们实际上是&amp;&amp;-ed 在一起。当你想要|| 时,一个长过滤器是不可避免的。

List<Person> inactivePersonList = 
    personList.stream()
              .filter(p -> p.getStatus().equals("inactive") ||
                           p.getId() == null && p.getStatus().equals("active"))
              .collect(Collectors.toList());

如果您有单独的 Predicate 对象,您可以将它们放在一起 .or()。

Predicate<Person> inactive = p -> p.getStatus().equals("inactive");
Predicate<Person> activeUnknown = p -> p.getId() == null && p.getStatus().equals("active");

List<Person> inactivePersonList = 
    personList.stream()
              .filter(inactive.or(activeUnknown))
              .collect(Collectors.toList());

甚至:

Predicate<Person> inactive = p -> p.getStatus().equals("inactive");
Predicate<Person> unknown = p -> p.getId() == null;
Predicate<Person> active = p -> p.getStatus().equals("active");

List<Person> inactivePersonList = 
    personList.stream()
              .filter(inactive.or(unknown.and(active)))
              .collect(Collectors.toList());

【讨论】:

    【解决方案2】:

    使用一个过滤器,但向用户添加一种方法,例如isActive():

    @Data
    public class Person {
       private Integer id;
       private String status;
       public boolean isActive() {
           return status.equals("active") || id != null;
       }
    }
    

    您最好更改区分活跃用户的方式。如果用户“活跃”但同时不活跃,那么您的类设计有问题。

    您可能希望使用enum Status { INACTIVE, ACTIVE } 代替字符串。

    或者使用额外的方法isUnknown 让你的过滤器更清晰。多次迭代所有人似乎不是一个好主意。

    【讨论】:

      猜你喜欢
      • 2017-04-13
      • 1970-01-01
      • 2020-11-23
      • 1970-01-01
      • 2021-06-02
      • 2012-11-09
      • 1970-01-01
      • 1970-01-01
      • 2019-04-11
      相关资源
      最近更新 更多