对相同字段但不同条件的 Java Stream 过滤

jlp*_*jlp 2 java java-8 java-stream

我有一个 Person 类:

@Data
public class Person {
   private Integer id;
   private String status;
}
Run Code Online (Sandbox Code Playgroud)

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

[{ 
    "id": null,
    "status": "inactive"
 },
 { 
    "id": 2,
    "status": "inactive"
 },
 { 
    "id": null,
    "status": "active"
 }]
Run Code Online (Sandbox Code Playgroud)

现在我需要找到所有状态为“非活动”的人,无论该人是否有 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());
Run Code Online (Sandbox Code Playgroud)

直播后的结果是没人接听。第一个人没有被选中,因为它没有通过第二个过滤器,最后一个人没有被选中,因为它没有通过第一个过滤器。

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

Joh*_*ica 7

过滤器是添加剂。他们有效地&&结合在一起。当你想要||一个长过滤器是不可避免的。

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

如果你有不同的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());
Run Code Online (Sandbox Code Playgroud)

甚至:

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());
Run Code Online (Sandbox Code Playgroud)