12

検索基準の次のマップがあります。

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

これは、このマップ述語アプローチをグーグルで検索したことからのリンクです。

4

2 に答える 2

13

あなたが望むのは、述語を Map に格納することではないようです。Predicate<Person>必要なのは、intパラメーターから作成できるマップに何かを格納できるようにすることです。したがって、あなたが望むのは次のようなものです:

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);
于 2015-08-23T13:09:50.160 に答える
5

私が理解しているように、あなたがしたいことは、名前付きのいくつかのパラメーターをオーバーライドすることですが、Predicateこれは混乱につながると思います。誰かがパイロットになる資格があるかどうかを判断する述語を求めている場合、それを呼び出すときに要件が何であるかを心配する必要はありません。

a を使用してその場で述語を生成するのはMap難しいでしょう。Map<String, PredicateFactory>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());
        });
于 2015-08-23T13:16:20.707 に答える