传递参数给Predicates

15

我有以下搜索条件的地图:

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

我正在以下方式使用这张地图:

pl.stream()
    .filter(search.getCriteria("allPilots"))
    .forEach(p -> {
        p.printl(p.getPrintStyle("westernNameAgePhone"));
    });

我想知道,如何将一些参数传递给谓词映射?

也就是说,我想通过字符串缩写从映射中获取谓词,并向获取的谓词中插入参数。

pl.stream()
    .filter(search.getCriteria("allPilots",45, 56))
    .forEach(p -> {
        p.printl(p.getPrintStyle("westernNameAgePhone"));
    });

这是我在谷歌上搜索出来的使用map-predicate方法的链接


1
你想要做的事情无法编译,并且你没有解释它应该实现什么功能。 - JB Nizet
我只是举了一个例子。当然,它不会被编译。这是我想做的:我想通过其字符串缩写从地图中获取谓词,并将参数插入到从地图中取出的谓词中。 - mr.M
1
参数将用于什么?在你的例子中,45的目标是什么? - JB Nizet
45和56是给定谓词“allPilots”的过滤参数,即如果飞行员的年龄不在年龄范围(45, 65)内,则该谓词应返回false。 - mr.M
1
好的。但是如果您传递"allDrivers"或"allDraftees"而不是"allPilots",那么这个参数会意味着什么呢?您似乎想同时做两件矛盾的事情:将谓词存储在地图中,以能够使用字符串键来执行谓词,而不必关心其实现方式,并且还可以通过传递参数来自定义谓词,尽管它们都以不同的方式完成任务。 - JB Nizet
@JBNizet,是的。我确实理解这里存在矛盾。但是,我目前关心的是在这样的映射中传递参数的可能性。 - mr.M
2个回答

14

看起来你想要的不是在Map中存储一个谓词。你想要的是能够将一个int参数转换成Predicate<Person>并存储到Map中。所以你想要的是这样的:

```java Map> map = new HashMap<>(); ```
Map<String, IntFunction<Predicate<Person>>> searchMap = new HashMap<>();

您可以这样填写:

searchMap.put("allPilots", maxAge -> 
    (p -> p.getAge() >= 23
     && p.getAge() <= maxAge));

你可以像这样使用它:

Predicate<Person> allPilotsAgedLessThan45 = 
    searchMap.get("allPilots").apply(45);

当然,如果您创建自己的功能接口,将更清晰明确:

@FunctionalInterface
public MaxAgePersonPredicateFactory {
    Predicate<Person> limitToMaxAge(int maxAge);
}
你仍然会以相同的方式填写地图,但使用时代码会更易读:
Predicate<Person> allPilotsAgedLessThan45 = 
    searchMap.get("allPilots").limitToMaxAge(45);

正是我所需要的。谢谢! - mr.M
1
鉴于OP想要传递两个int参数,这应该是BiFunction<Integer,Integer,Predicate<Person>>而不是IntFunction吧? - KumarM
@KumarM 我在问题中错过了第二个参数,只注意到了45。但是,如果他需要两个参数,工厂的签名将不得不更改。 - JB Nizet

9
据我所知,您想要做的是覆盖命名“Predicate”中的一些参数,但我认为这会导致混淆。如果我正在寻求决定某人是否有资格成为飞行员的谓词,我不想在调用谓词时担心了解要求。
使用“Map”即时生成谓词会很棘手——我认为最好的方法是改为具有“Map ”的形式,其中“PredicateFactory”是一种复杂的类,根据一些参数生成谓词:
Map<String, PredicateFactory<T>> predicates = new HashMap<>();

public Predicate<T> get(String name, Object... params) {
    return predicates.get(name).apply(params);
}

在我看来,生成“动态”谓词更好的方法是使用静态方法:
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;
    }
}

然后,根据需要轻松创建描述性谓词:

private static Predicate<Person> personIsOfDrivingAge() {
    return personIsAtLeast(17);
}

private static Predicate<Person> couldBePilot() {
    return personIsBetweenAges(23, 65).and(personIsMale());

}

如果您想通过覆盖一些参数来实现某些目标,可以使用组合的方式更清晰地表达:

people.stream()
        .filter(couldBePilot().and(personIsBetweenAges(45, 56)))
        .forEach(person -> {
            System.out.println(person.getAge() + ", " + person.getGender());
        });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接