Java Stream filtering on same fields but different criteria

jlp :

I have a Person class:

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

And I have a List of Person called personList:

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

Now I need to find all people whose status is "inactive" regardless if the person has an Id or not. If a person doesn't have an Id, but the status is "active", include that person as well. I am using Java stream to do the filtering:

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

The result after streaming is that nobody got picked up. The first person didn't get picked up because it didn't pass the second filter, the last person didn't get picked up because it didn't pass the first filter.

I think I can fix it by combining the two filters into one using OR, but I am trying to make each filter simple, so before I make the change, I would like to ask if there is a better way to do it. Thanks.

John Kugelman :

Filters are additive. They're effectively &&-ed together. When you want || a long filter is unavoidable.

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

If you had separate Predicate objects you could .or() them together.

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());

Or even:

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());

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=26964&siteId=1