Filtering nested lists using lambda

Viewed 2441

I am having a List<User> users. I would like to filter the list basing on two conditions.

  1. Matching the UserID
  2. Matching the FilterName

    public class User implements Entity {

        public User() {
        }
    
        private String userName;
        private String userId;
        private List<Filter> filters;
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public String getUserId() {
            return userId;
        }
    
        public void setUserId(String userId) {
            this.userId = userId;
        }
    
        public List<Filter> getFilters() {
            return filters;
        }
    
        public void setFilters(List<Filter> filters) {
            this.filters = filters;
        }
    
    }
    

Here is the method signature

List<User> users = getUsersList();
public List<User> query(String userID,String filterName){
    users.stream().filter(element -> element.getUserID().equals(userID) && element.getFilters().stream().filter(f -> f.getFilterName().equals(filterName))).collect(Collectors.toList());

}

The above method does not work as i am filtering basing on a element and a stream. Can anybody help me with the right way of filtering lists and nested lists.

I also tried this way

users.stream().filter(e -> e.getUserId().equals(predicate.getUserID())).collect(Collectors.toList()).stream().filter(f -> f.getFilters().stream().filter(fe -> fe.getName().equals(predicate.getFilterName()))).collect(Collectors.toList());

either ways i am getting the below error

Type mismatch: cannot convert from Stream to boolean

Tried Adiel Loingers suggestion. It worked

java.util.function.Predicate<Filter> con = e -> e.getName().equals(predicate.getFilterName());
            result = users.stream().filter(p -> p.getUserId().equals(predicate.getUserID()) && p.getFilters().stream().anyMatch(con)).collect(Collectors.toList());
2 Answers

You shall change

element.getFilters().stream().filter(f -> f.getFilterName().equals(filterName))

to

element.getFilters().stream().anyMatch(f -> f.getFilterName().equals(filterName))

which would return boolean true for any match of the predicate specified which is same as specified in filter in your case.

I think it may help you, second conditions gets stream of all filters and find your filter name present in that filter is list, if so returns true otherwise false.

users.stream()
        .filter(element -> element.getUserId().equals(userId)
            && element.getFilters().stream().filter(f -> f.filterName.equals(FilterName)).findAny().isPresent())
        .collect(Collectors.toList());
Related