Search code examples
javalambdapredicates

Pass parameters to Predicates


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.


Solution

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