2015-08-23 13 views
5

Mam następujący mapa z kryteriów wyszukiwania: Jak mogęparametry podaje do orzeczników

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

chciałbym wiedzieć:

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

Używam tej mapy w następujący sposób przekazać niektóre parametry do mapy predykatów?

tj. Chciałbym pobrać predykat z mapy za pomocą jego skrótu i ​​wstawić parametr do usuniętego z predykatu mapy.

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

Oto link z I googled to podejście predykatu mapy.

+1

Co chcesz zrobić, to nie skompilowałem, a ty nie wyjaśniłeś, co ma robić. –

+0

Po prostu podałem przykład. Pewnie, że się nie skompiluje. Oto, co chciałbym zrobić: Chciałbym uzyskać predykat z mapy za pomocą jego skrótu i ​​wstawić parametr do usuniętego z predykatu mapy. –

+1

Do czego służy ten parametr? Jaki jest cel 45 w twoim przykładzie? –

Odpowiedz

4

Wygląda na to, że nie chodzi o przechowywanie predykatu na mapie. To, czego chcesz, to móc zapisać coś na mapie, która jest w stanie utworzyć Predicate<Person> z parametru int. Więc co chcesz, jest coś takiego:

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

Można by ją wypełnić w ten sposób:

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

I woult go używać tak:

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

oczywiście, że będzie być bardziej przejrzystym, jeśli utworzono własny interfejs funkcji:

@FunctionalInterface 
public MaxAgePersonPredicateFactory { 
    Predicate<Person> limitToMaxAge(int maxAge); 
} 

Nadal będzie wypełnić mapę w ten sam sposób, ale można wtedy kod nieco bardziej redable podczas używania go:

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

Dokładnie tego, czego szukałem. Dziękuję Ci! –

+1

Biorąc pod uwagę, że OP chce przekazać w dwóch int params, nie powinno to być BiFunction > zamiast IntFunction? – KumarM

+0

@KumarM Brakowało mi drugiego parametru w pytaniu i zauważyłem tylko 45. Ale tak, jeśli potrzebuje dwóch parametrów, podpis fabryki będzie musiał się zmienić. –

1

Jak rozumiem, co chcesz zrobić, to zastąpić niektóre parametry w nazwana Predicate , ale myślę, że to doprowadzi do zamieszania. Jeśli pytam o predykat, który określa, czy ktoś kwalifikuje się do bycia pilotem, nie chcę martwić się o to, jakie są wymagania w czasie, kiedy to nazywam.

Generowanie predykaty w locie przy użyciu Map byłoby trudne - myślałem najpiękniejszy sposób byłoby zamiast mieć Map<String, PredicateFactory>, gdzie PredicateFactory jest jakiś skomplikowany klasy, który generuje predykatów podane niektóre parametry:

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

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

moim zdaniem lepszym sposobem generowania „dynamiczne” predykatów jest z metod statycznych:

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

to wtedy trywialne stworzyć opisowych predykaty wymagane:

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

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

} 

a coś takiego starasz się osiągnąć z nadrzędnymi niektórych parametrów pozostaje jasny z odrobiną składzie:

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