2015-06-17 7 views
5

Sto spostando del codice su java8, provando (a volte costringendo me stesso) all'utilizzo di stream e lambda, e non mi sento ancora a mio agio con loro.Come ottenere il primo non facoltativo <T> da un elenco di Opzionale <T>

Ho alcuni metodi in una classe che convalida un oggetto business. Ogni metodo sembra

Optional<Fail> validate1(BusinessObject bo) 

dove Fail è un enum che descrive in qualche modo l'errore, e se c'è nessun errore il metodo restituisce Optional.empty(). Non è necessario raccogliere tutti gli errori, ma restituire il primo errore, senza eseguire le seguenti convalide.

Quello che sto facendo è

//first convert methods to suppliers 
Supplier<Optional<Fail>> validate1=() -> validate1(bo); 
Supplier<Optional<Fail>> validate2=() -> validate2(bo); 
Supplier<Optional<Fail>> validate3=() -> validate3(bo); 
//then some stream magic 
return Stream.of(validate1, validate2, validate3) 
    .map(Supplier::get) 
    .filter(f -> f.isPresent()) 
    .findFirst() 
    .orElse(Optional.empty()); //without the orElse, no error would return 
             // Optional(Optional.empty()) 
             // instead of Optional.empty() 

Funziona, fa il lavoro, ma non esegue i metodi non necessari, è leggibile (sarebbe più leggibile se Optional.orElse sono stati nominati getOrElse, ma è fuori dalla mia portata). Quello che sto cercando di scoprire è se questo è un modo ragionevole di fare ciò che voglio, se questo codice sarebbe considerato "buono stile" o "idiomatico java8", o sto usando male Stream o Opzionale, o manco qualcosa di ovvio.

L'idea di restituire il primo Opzionale non vuoto o Opzionale vuoto se sono tutti vuoti sembra abbastanza generale da pensare che ci sia un modo ufficiale per farlo, qualcosa nella parte posteriore della mia testa sta urlando "Monade!" ma la mia ignoranza su Haskell è quasi perfetta, quindi non lo so.

+0

Sembra che il codice abbastanza ragionevole stile. –

+0

Se fossi in te probabilmente fare 'Stream.of (validate1 (bo), validate1 (bo), validate1 (bo))' piuttosto che usare un fornitore. – Jatin

+0

@Jatin che chiamerebbe immediatamente tutti i metodi di validazione. OP vuole chiamarli solo se necessario. – Misha

risposta

2

Optional è molto simile a Stream con 0 o 1 elementi in esso. Tuttavia non implementa Stream, né ha un metodo stream() (come fanno le raccolte).

Tuttavia, non è così difficile la conversione di un Optional<T> ad un Stream<T>, questa funzione fa:

public static <T> Function<Optional<? extends T>, Stream<T>> asStream() { 
    return op -> op.map(Stream::of).orElseGet(Stream::empty); 
} 

Con questo metodo disponibile si può semplicemente utilizzare flatMap:

Stream.of(validate1, validate2, validate3) 
     .map(Supplier::get) 
     .flatMap(asStream()) 
     .findFirst(); 
+0

Java 9 [avrà] (http://download.java.net/jdk9/docs/api/java/util/Optional.html#stream--). Tuttavia, '.flatMap (asStream())' o '9flatMap di Java 9 (Optional :: stream)' non è diverso da '.filter (Optional :: isPresent) .map (Optional :: get)'. Non risponde alla domanda dell'OP sulla validità del concetto in generale ... – Holger