2015-08-23 10 views
5

Ich habe die folgende Karte von den Suchkriterien:Pass Parameter Prädikate

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

Ich bin mit dieser Karte in der folgenden Art und Weise:

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

Ich möchte wissen, wie kann ich einige Parameter in die Karte der Prädikate übertragen?

I.e. Ich möchte Prädikat von einer Karte durch seine Zeichenkettenabkürzung erhalten und einen Parameter in das Herausnehmen von einem Kartenprädikat einfügen.

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

Hier ist die link aus ich diese Karte-Prädikat Ansatz gegoogelt aus.

+1

Was würden Sie tun mögen nicht kompilieren, und du hast nicht erklärt, was es tun soll. –

+0

Ich habe nur ein Beispiel gegeben. Sicher, es wird nicht kompiliert. Hier ist, was ich gerne tun würde: Ich möchte ein Prädikat von einer Karte durch seine Abkürzung Zeichenfolge erhalten und fügen Sie einen Parameter in die aus einem Kartenprädikat herausgenommen. –

+1

Wofür wird der Parameter verwendet? Was ist das Ziel von 45 in deinem Beispiel? –

Antwort

4

Es scheint, dass das, was Sie wollen, ist nicht ein Prädikat in einer Karte zu speichern. Was Sie wollen, ist in der Lage sein, etwas in einer Karte zu speichern, die ein Predicate<Person> von einem int Parameter erstellen kann. Also, was Sie wollen, ist so etwas wie dieses:

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

Sie würden es auf diese Weise füllen:

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

Und Sie woult es wie folgt verwendet werden:

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

Natürlich, das wäre Seien Sie klarer, wenn Sie Ihre eigene Funktionsschnittstelle erstellt haben:

Sie würden immer noch die Karte die gleiche Art und Weise füllen, aber Sie würden dann etwas mehr redable Code haben, wenn es mit:

Predicate<Person> allPilotsAgedLessThan45 = 
    searchMap.get("allPilots").limitToMaxAge(45); 
+0

Genau das, was ich gesucht habe. Vielen Dank! –

+1

Vorausgesetzt, das OP möchte zwei int-Parameter übergeben, sollte dies nicht eine BiFunction sein > anstelle einer IntFunktion? – KumarM

+0

@KumarM Ich verpasste den zweiten Parameter in der Frage und bemerkte nur die 45. Aber ja, wenn er zwei Parameter benötigt, muss sich die Signatur der Fabrik ändern. –

1

Wie ich es verstehe, was Sie wollen, zu tun ist, außer Kraft setzen einige Parameter in einer benannten Predicate , aber ich denke, das wird zu Verwirrung führen. Wenn ich für das Prädikat bin gefragt, wenn jemand bestimmt ist berechtigt, einen Pilot zu sein, ich will nicht, um zu wissen, was die Anforderungen an die Zeit sind zu befürchten haben, wenn ich es nennen.

generieren Prädikate on the fly ein Map mit wäre heikel - ich würde denken, die schönste Art und Weise statt wäre, ein Map<String, PredicateFactory> zu haben, wo die PredicateFactory eine Art komplizierter Klasse, die Prädikate gegeben einige Parameter erzeugt:

Map<String, PredicateFactory<T>> predicates = new HashMap<>(); 

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

meiner Meinung nach, der bessere Weg „dynamische“ Prädikate zu erzeugen, ist mit statischen Methoden:

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

Es ist dann trivial deskriptive Prädikate zu erstellen, wie benötigt:

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

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

} 

Und das, was Sie versuchen, mit zwingenden einigen Parametern zu erreichen, bleibt mit etwas Zusammensetzung klar:

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