2014-05-21 5 views
5

Ho una lista e voglio un elemento dalla lista che corrisponde a un predicato. Sto trovando un elemento dalla lista che corrisponde al primo predicato, se il primo predicato non restituisce true, corrisponde al secondo predicato.Trova predicato corrispondente e utilizzando iterable.tryFind restituisce l'elemento dall'elenco in java

Ecco un esempio:

Case1:

result = iterable.tryFind(List, Predicates.or(predicate1, predicate2)).orNull(); 

Il problema con questo pezzo di codice è che trova il primo elemento che corrisponde a qualsiasi di quei predicati. Anche se il secondo elemento nella lista corrisponde al primo predicato, che nel mio caso dovrebbe avere una priorità più alta. In questo caso, mi aspetto che il risultato qui sia un secondo elemento, ma il primo elemento (dato che è il primo elemento che corrisponde a uno di quei predicati).

Case2:

result = iterable.tryFind(List, Predicates.and(predicate1, predicate2)).orNull(); 

Ciò, ovviamente, non funziona, se il primo predicato restituisce false.

Caso 3:

result = iterable.tryFind(List, predicate1).orNull(); 

if(result == null) 
result = iterable.tryFind(List, predicate2).orNull(); 

Questo lavoro per me, ma sembra disordinato e contrasta con l'obiettivo della programmazione funzionale.

C'è un altro modo per recuperare un elemento da un elenco che funzionerà per il mio scenario?

+2

lo fa realmente sconfiggere lo scopo solo perché si ha filiali? Cosa ti infastidisce: il ramo, la doppia iterazione, qualcos'altro? È possibile ottenere il risultato con una singola iterazione, eseguendo il mapping anziché il filtro, in modo da sapere quale corrispondenza si è verificata, filtrando gli elementi che non corrispondevano a nessun predicato e riducendo per mantenere la prima corrispondenza, con la precedenza data alla corrispondenza da il primo predicato. Sarà davvero meno disordinato (in Java)? –

+0

@FrankPavageau: i rami mi stanno dando fastidio. Mi aspettavo che funzionasse senza separare i predicati. Quello che stai suggerendo sarà simile a questo, se avessi capito bene. Immagino che questo sia l'unico modo per farlo funzionare. – LifeStartsAtHelloWorld

+1

Non penso che "programmazione funzionale" significhi rimuovere tutto il flusso di controllo: qualcosa deve farlo ad un certo punto e quando si filtra una collezione è solo nascosta nel metodo, non rimossa. –

risposta

5

È possibile utilizzare Optional.or invece di Predicate.or per ottenere ciò che si vuole:

result = Iterables.tryFind(list, predicate1) 
     .or(Iterables.tryFind(list, predicate2)) 
     .orNull(); 
+2

Il problema è che "Iterables.tryFind (list, predicate2)" viene sempre valutato. Avresti bisogno di '||' da Javascript o 'o' da LISP. In Java poteva funzionare solo se 'tryFind' era pigro e' Optional' avrebbe valutato il suo argomento quando necessario. – maaartinus

+0

Questo è lo svantaggio della mia soluzione. Il pigro 'tryFind' potrebbe essere implementato con' Supplier', ma funziona solo se non restituisce 'absent'. – phlogratos

Problemi correlati