I have the following map of the search criteria:
private final Map<String, Predicate> searchMap = new HashMap<>();
private void initSearchMap() {
Predicate<Person> allDrivers = p -> p.getAge() >= 16;
Predicate<Person> allDraftees = p -> p.getAge() >= 18
&& p.getAge() <= 25
&& p.getGender() == Gender.MALE;
Predicate<Person> allPilots = p -> p.getAge() >= 23
&& p.getAge() <=65;
searchMap.put("allDrivers", allDrivers);
searchMap.put("allDraftees", allDraftees);
searchMap.put("allPilots", allPilots);
}
I am using this map in the following way:
pl.stream()
.filter(search.getCriteria("allPilots"))
.forEach(p -> {
p.printl(p.getPrintStyle("westernNameAgePhone"));
});
I would like to know, how can I pass some parameters into the map of predicates?
I.e. I would like to get predicate from a map by its string abbreviation and insert a parameter into the taken out from a map predicate.
pl.stream()
.filter(search.getCriteria("allPilots",45, 56))
.forEach(p -> {
p.printl(p.getPrintStyle("westernNameAgePhone"));
});
Here is the link from I googled out this map-predicate approach.
The predicate is a predefined functional interface in Java defined in the java. util. Function package. It helps with manageability of code, aids in unit-testing, and provides various handy functions.
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. Represents a predicate (boolean-valued function) of one argument. This is a functional interface whose functional method is test(Object) .
Java IntPredicate interface is a predicate of one int-valued argument. It can be considered an operator or function that returns a value either true or false based on certain evaluation on the argument int value. IntPredicate is a functional interface whose functional method is boolean test(int a) .
As I understand it, what you want to do is override some parameters in a named Predicate
, but I think this will lead to confusion. If I'm asking for the predicate that determines if somebody is eligible to be a pilot, I don't want to have to worry about knowing what the requirements are at the time when I call it.
Generating predicates on the fly using a Map
would be tricky - I'd think the nicest way would be to instead have a Map<String, PredicateFactory>
, where the PredicateFactory
is some sort of complicated class that generates predicates given some parameters:
Map<String, PredicateFactory<T>> predicates = new HashMap<>();
public Predicate<T> get(String name, Object... params) {
return predicates.get(name).apply(params);
}
To my mind, the better way to generate "dynamic" predicates is with static methods:
public class PredicatesQuestion {
public static void main(String[] args) {
List<Person> people = Arrays.asList(new Person(20, Gender.MALE),
new Person(45, Gender.FEMALE), new Person(50, Gender.MALE),
new Person(65, Gender.MALE));
people.stream()
.filter(personIsBetweenAges(16, 25))
.forEach(person -> {
System.out.println(person.getAge() + ", " + person.getGender());
});
}
private static Predicate<Person> personIsMale() {
return person -> person.getGender() == Gender.MALE;
}
private static Predicate<Person> personIsBetweenAges(int lower, int upper) {
return personIsAtLeast(lower).and(personIsYoungerThan(upper));
}
private static Predicate<Person> personIsAtLeast(int age) {
return person -> person.getAge() >= age;
}
private static Predicate<Person> personIsYoungerThan(int age) {
return person -> person.getAge() < age;
}
}
It's then trivial to create descriptive predicates as required:
private static Predicate<Person> personIsOfDrivingAge() {
return personIsAtLeast(17);
}
private static Predicate<Person> couldBePilot() {
return personIsBetweenAges(23, 65).and(personIsMale());
}
And the sort of thing you're trying to achieve with overriding some parameters remains clear with a bit of composition:
people.stream()
.filter(couldBePilot().and(personIsBetweenAges(45, 56)))
.forEach(person -> {
System.out.println(person.getAge() + ", " + person.getGender());
});
It seems that what you want is not to store a predicate in a Map. What you want is to be able to store something in a map that is able to create a Predicate<Person>
from an int
parameter. So what you want is something like this:
Map<String, IntFunction<Predicate<Person>>> searchMap = new HashMap<>();
You would fill it that way:
searchMap.put("allPilots", maxAge ->
(p -> p.getAge() >= 23
&& p.getAge() <= maxAge));
And you would use it like this:
Predicate<Person> allPilotsAgedLessThan45 =
searchMap.get("allPilots").apply(45);
Of course, it would be clearer if you created your own functional interface:
@FunctionalInterface
public MaxAgePersonPredicateFactory {
Predicate<Person> limitToMaxAge(int maxAge);
}
You would still fill the map the same way, but you would then have slightly more readable code when using it:
Predicate<Person> allPilotsAgedLessThan45 =
searchMap.get("allPilots").limitToMaxAge(45);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With