Reputation: 2184
I have a requirement where I have to filter object from list based on multiple dynamic filter condition.
I have already written code by looping over objects and then all filter and returning false if any condition doesn't match. The code that I have written is as
Map<String, String> obj1 = new HashMap<>();
obj1.put("id", "1");
obj1.put("name", "name1");
obj1.put("dept", "IT");
obj1.put("sex", "M");
Map<String, String> obj2 = new HashMap<>();
obj2.put("id", "2");
obj2.put("name", "name2");
obj2.put("dept", "IT");
obj2.put("sex", "M");
Map<String, String> obj3 = new HashMap<>();
obj3.put("id", "3");
obj3.put("name", "name3");
obj3.put("dept", "DEV");
obj3.put("sex", "F");
ArrayList<Map<String, String>> employees = new ArrayList<>(Arrays.asList(obj1,obj2,obj3));
Map<String, String> filterCondition = new HashMap<>();
filterCondition.put("dept", "IT");
filterCondition.put("sex", "M");
List<Map<String, String>> filteredEmployee = new ArrayList<>();
for(Map<String,String> employee:employees){
if(isValid(filterCondition, employee)){
filteredEmployee.add(employee);
}
}
System.out.println(filteredEmployee);
isValid method is as
private static boolean isValid(Map<String, String> filterCondition, Map<String, String> employee) {
for(Entry<String, String> filterEntry:filterCondition.entrySet()){
if(!employee.get(filterEntry.getKey()).equals(filterEntry.getValue())){
return false;
}
}
return true;
}
Is there any better way to achieve it if filters that I am getting is coming dynamically.
I have already seen some answer in stackoverflow as here ,but with no help
Upvotes: 1
Views: 2182
Reputation: 21
Maybe you can use for-loop with Stream:
Stream<Map<String, String>> employeeStream = employees.stream();
for (Map.Entry<String, String> entry : filterCondition.entrySet()) {
employeeStream = employeeStream.filter(map -> entry.getValue()
.equals(map.get(entry.getKey())));
}
List<Map<String, String>> filteredEmployee = employeeStream.collect(Collectors.toList());
Upvotes: 2
Reputation: 4081
Combine all filters as a single Predicate (using stream, reduce, and predicate composition):
Predicate<Map<String, String>> allConditions = filterCondition
.entrySet()
.stream()
.map(ThisClass::getAsPredicate)
.reduce((employee) -> true, Predicate::and);
Then just use Stream.filter()
List<Map<String, String>> filteredEmployees = employees
.stream()
.filter(allConditions)
.collect(Collectors.toList());
Helper function:
private static Predicate<Map<String, String>> getAsPredicate(Map.Entry<String, String> filter) {
return (Map<String, String> employee) -> employee.get(filter.getKey()).equals(filter.getValue());
}
Upvotes: 4