2015-06-17 13 views
5

Przenoszę kod do java8, próbując (czasem zmuszając się) do korzystania z strumieni i lambdy, i nie jestem jeszcze z nimi dobrze.Jak uzyskać pierwszy pusty Opcjonalnie <T> z listy Opcjonalne <T>

Mam niektóre metody w klasie, które sprawdzają poprawność obiektu biznesowego. Każda metoda wygląda

Optional<Fail> validate1(BusinessObject bo) 

gdzie Fail jest enum, że jakoś opisuje błąd, a jeśli nie ma błędu metoda zwraca Optional.empty(). Nie muszę zbierać wszystkich błędów, ale zwracam pierwszy błąd, bez wykonywania następujących sprawdzeń.

Co robię jest

//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() 

To działa, to nie praca, to nie wykonuje niepotrzebnych metod, to czytelny (to byłoby bardziej czytelne jeśli Optional.orElse zostały nazwane getOrElse, ale to jest poza moim zasięgiem). Próbuję się dowiedzieć, czy jest to rozsądny sposób robienia tego, co chcę, jeśli ten kod byłby uważany za "dobry styl" lub "idiomatic java8", czy też niewłaściwie używam strumienia lub opcjonalnie, lub brakuje czegoś oczywistego.

Pomysł zwrócenia pierwszego niepustego Opcjonalnego lub pustego Opcjonalnego, jeśli wszystkie są puste, wygląda na dość ogólny, by sądzić, że istnieje oficjalny sposób na zrobienie tego, coś z tyłu głowy wykrzykuje "Monady!" , ale moja nieznajomość Haskella jest prawie idealna, więc nie wiem.

+0

Wygląda całkiem rozsądnym kodu styl. –

+0

Gdybym był tobą, prawdopodobnie użyłbym 'Stream.of (validate1 (bo), validate1 (bo), validate1 (bo)) zamiast używać dostawcy. – Jatin

+0

@Jatin, który natychmiast wywoła wszystkie metody sprawdzania poprawności. OP chce je wywoływać tylko w razie potrzeby. – Misha

Odpowiedz

2

Optional jest bardzo podobny do Stream z 0 lub 1 elementami w nim. Jednak nie implementuje ona Stream, ani nie ma metody stream() (jak robią to kolekcje).

Jednak to nie takie trudne przekształcania Optional<T> do Stream<T>, ta funkcja robi:

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

Z tej metody dostępnej można po prostu użyć flatMap:

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

Java 9 [będzie] (http://download.java.net/jdk9/docs/api/java/util/Optional.html#stream--). Niemniej jednak '.flatMap (asStream())' lub Java '' .flatMap (Opcjonalnie :: stream) 'nie różni się od' .filter (Opcjonalnie :: isPresent) .map (Opcjonalnie :: get) '. Nie odpowiada na pytanie PO dotyczące ważności tej koncepcji w ogóle ... – Holger