Filter List based of optional List

Pete :

I have an optional list of Integers, Optional<List<Integer>> id.

I have a list of many different people. List<People> people.

I have a filter method that takes takes the optional filter. The code calls the repository to get a list of people and, if the Optional list of id's is populated, will filter the people within the list against the id's. People.getId().

I want to use the steams API to avoid editing the original list. I have tried something like this

 return people.stream()
            .filter(p -> !request.getId().orElseGet(ArrayList::new).contains(p.getId()))
            .collect(Collectors.toList());

The spec is.

  • if no id's, return all
  • if id's provided - filter
  • if id's provided and no matches, return empty list

The above fails when the no id's match, it returns a full list.

Optional<List<Integer>> ids = Optional.of(Arrays.asList(1, 2, 3));
List<People> people = datasource...

List<People> filter (Optional < List < Integer >>> ids) {
    List<People> confusion = people.steam(). ?
    return confusion;
}

Any and all help is greatly appreciated!

Fullstack Guy :

if no id's, return all

Firstly, You just need an || condition. If the the Optional is empty then the Optional.isPresent() would be false, so adding a !ids.isPresent() before the || will return you all the items from the filter as the || is a short-circuit operation as the condition on the left of the || is true the entire condition will be true.

if id's provided - filter

Secondly, the ! needs to be removed from your check and you need this check on the right of the ||: ids.get().contains(p.getId()) to filter using the list of ids from the Optional.

if id's provided and no matches, return empty list

Thirdly, if ids is present then the second check will be evaluated as the first check !ids.isPresent() becomes false. The People object will be checked if the id matches with the list from the Optional if nothing matches an empty list is returned.

So all three can be applied below:

List<People> list = people.stream()
                        .filter(p -> !ids.isPresent() || ( ids.get().isEmpty() || ids.get().contains(p.getId())))
                        .collect(Collectors.toList());

Also, it would be better if you would use an Optional<Set<Integer>> instead of a Optional<List<Integer>>, then contains() would be constant time operation.

Guess you like

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