wandermonk
wandermonk

Reputation: 7356

Filtering nested lists using lambda

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

Upvotes: 4

Views: 2846

Answers (2)

Sandeep Kokate
Sandeep Kokate

Reputation: 845

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

Upvotes: 1

Naman
Naman

Reputation: 31878

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.

Upvotes: 3

Related Questions