Configurable external filtering using Java lambdas
Suppose I have external JSON:
[{
"condition": "equals",
"field": "name",
"value": "jack"
},
{
"condition": "greater",
"field": "age",
"value": 25
}
]
What this means, I want to check in the list of Person objects for people named "jack"
and age > 25
. It's pretty easy with Java 8 filtering (example shown as filtering by name only).
However, I want this filter to be customizable and also to apply multiple filters. Assuming the Person pojo below (which is self-evident) accepts a name and age, how can I make the filters dynamic or customizable?
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Accessors and Mutators
}
List<Person> persons = Arrays.asList(
new Person("mkyong", 30),
new Person("jack", 20),
new Person("lawrence", 40)
);
Person result1 = persons.stream() // Convert to steam
.filter(x -> "jack".equals(x.getName())) // we want "jack" only
.findAny() // If 'findAny' then return found
.orElse(null);
I am expecting a list of a Person object that ultimately satisfies the criterion.
source to share
It has nothing to do with streams
per se as far as I can tell. This filtering method is just Predicate
one that can be provided as an instance, for example from a factory method that you could create.
static Predicate<Person> fromName(String value){
return p -> p.getName().equals(value);
}
Let's assume you have another method:
static Predicate<Person> fromAge(int value) {
return p -> p.getAge() == value;
}
Since Predicate.and
, Predicate.or
exists, you can do:
fromAge(12).and(fromName("jack"));
thus linking your predicates
source to share
There are two approaches to this.
Or, you just chain the required filters inline:
Person result1 = persons.stream()
.filter(x -> "jack".equals(x.getName()))
.filter(x -> 25 > x.getAge()) // new filter
.findAny()
.orElse(null);
Or do you have your own class that implements Predicate<Person>
.
In this case, you can use the builder pattern to build the predicate step by step.
The difficulties you will have to face are as follows:
- Handling boolean relations between terms (
&&
vs||
) - Handling nested boolean relations (
(a && b) || c
nota && (b || c)
)
Please note that Predicate
is convenient methods and
and or
chain predicates.
source to share