Java 将参数传递给谓词

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32166471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:06:19  来源:igfitidea点击:

Pass parameters to Predicates

javalambdapredicates

提问by mr.M

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 linkfrom I googled out this map-predicate approach.

这里是链接从我用Google搜索这个地图谓语方法。

采纳答案by JB Nizet

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 intparameter. So what you want is something like this:

似乎您想要的不是将谓词存储在 Map 中。您想要的是能够在能够Predicate<Person>int参数创建 a 的地图中存储一些东西。所以你想要的是这样的:

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

回答by Edd

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.

据我了解,您想要做的是覆盖 named 中的一些参数Predicate,但我认为这会导致混淆。如果我要求确定某人是否有资格成为飞行员的谓词,我不想在我调用它时担心知道要求是什么。

Generating predicates on the fly using a Mapwould be tricky - I'd think the nicest way would be to instead have a Map<String, PredicateFactory>, where the PredicateFactoryis some sort of complicated class that generates predicates given some parameters:

使用 a 即时生成谓词Map会很棘手 - 我认为最好的方法是使用 a Map<String, PredicateFactory>,其中 thePredicateFactory是某种复杂的类,可以在给定一些参数的情况下生成谓词:

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