2015-08-28 20 views
10

więc obecnie mamUnwrap opcjonalnego tylko wtedy, gdy jest on obecny

String uri = website.getUri(); 
Optional<PageDetail> pageDetail = webClient.getDetailOfUri(uri); 
String displayName; 
String description; 
if (pageDetail.isPresent()) { 
    displayName = pageDetail.get().getName(); 
    description = pageDetail.get().getDescription(); 
} else { 
    displayName = uri; 
    description = ""; 
} 

Wołam metodę getDetailOfUri(uri), która zwraca Optional<PageDetail>, i chciałbym, aby ustawić ciągi displayName i description na wartościach PageDetail pól obiektu, jeśli jest obecny. W przeciwnym razie chciałbym ustawić go na pewne wartości domyślne.

Moje pytanie brzmi, czy istnieje lepszy sposób na przepisanie tego? Mój obecny kod wydaje się nieco długi i nużący, i chciałbym wiedzieć, czy jest to bardziej zwięzły sposób.

+1

oprócz użycia "bool? IfTrue: ifFalse" Nie widzę tego –

+0

Tak, potrójna instrukcja nie jest opcją. – yiwei

Odpowiedz

13

można napisać:

String uri = website.getUri(); 
Optional<PageDetail> pageDetail = webClient.getDetailOfUri(uri); 
String displayName = pageDetail.map(PageDetail::getName).orElse(uri); 
String description = pageDetail.map(PageDetail::getDescription).orElse(""); 

Jeśli Optional nie jest ustawiona, map zwróci ten sam unset Optional. W przeciwnym razie zostanie odwzorowany na Optional zawierający wynik getName(). Następnie możemy użyć orElse, aby zwrócić wartość domyślną, gdy Optional jest rozbrojony.

+0

Dzięki! Wciąż jestem nowicjuszem dla lamdasów Java 8, więc poświęcam trochę czasu, aby omówić to. Ale to wygląda na to, czego potrzebuję! – yiwei

+0

@Andreas my 'getName()'/'PageDetail' nie jest ostateczny, ale' p' gwarantuje, że nie jest podklasą 'PageDetail. To powinno się udać, prawda? – yiwei

+0

Nie podoba mi się ta odpowiedź, ponieważ jeśli PageDetail ma więcej niż 2 pola (displayName i description), będziesz miał wiele map(). Lub wywołania eEse. Wolę mieć instancję zastępczą i pracować z nie-Opcjonalną instancją. – pyb

8

Zastosowanie Optional#orElseGet że bierze Supplier:

// Reference to the constructor, but you could use a Factory, etc. 
// All you need is a method that returns a PageDetail 
// See the Javadoc and http://www.byteslounge.com/tutorials/java-8-consumer-and-supplier 
Supplier<PageDetail> emptySupplier = PageDetail::new; 

pageDetail = pageDetail.orElseGet(emptySupplier); 
// works the same 
//pageDetail = pageDetail.orElseGet(() -> new PageDetail()); 

String displayname = pageDetail.getName(); 
String uri = pageDetail.getUri(); 

orElseGet stworzy pusty PageDetail tylko wtedy, gdy opcjonalny ma wartość null. Dzięki temu zasoby twojego kodu są wydajne.

edycji/próbkę compilable: https://ideone.com/9h1Ntg

Edit: Dzięki wszystkim za opinie! W rzeczywistości dodałem orElseGet, które uważam za lepsze. Poprawiłem również kod, aby odwijać końcówkę Optional, aby pageDetail było rzeczywistą instancją .

Edytuj 2: Dodano inny przykład składni i przykład edytowalny/kompilacyjny.

+2

Nie, to jest złe, ponieważ musisz wywołać 'getName()', aby uzyskać nazwę wyświetlaną. – Tunaki

+0

orElse (T other), not orElseGet (Dostawca inny) – leoger

+0

@Tunaki, nie rozumiem twojego komentarza. Możesz wyjaśnić? – leoger

Powiązane problemy