2015-08-28 15 views
10

So derzeit Ich habeAbwickelwerkzeug ein Optional nur, wenn es vorhanden ist

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

Ich rufe die getDetailOfUri(uri)-Methode, die eine Optional<PageDetail> zurückgibt, und ich möchte die Saiten setzen displayName und description zu den Werten der PageDetail Objektfelder, wenn es vorhanden ist. Ansonsten möchte ich es auf einige Standardwerte setzen.

Meine Frage ist, gibt es eine bessere Möglichkeit, dies umzuschreiben? Mein aktueller Code scheint ein bisschen lang und langwierig zu sein, und ich würde gerne wissen, ob es eine prägnantere Möglichkeit gibt, dies zu tun.

+1

neben der Verwendung von "bool? IfTrue: ifFalse" Ich sehe es nicht –

+0

Yeah die ternäre Aussage ist keine Option. – yiwei

Antwort

13

könnten Sie schreiben:

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(""); 

Wenn die Optional nicht gesetzt ist, map die gleiche ungesetzt Optional zurück. Andernfalls wird es auf Optional mit dem Ergebnis getName() abgebildet. Dann können wir orElse verwenden, um einen Standardwert zurückzugeben, wenn Optional nicht festgelegt ist.

+0

Danke! Ich bin immer noch sehr neu in Java 8's lamdas, also brauche ich eine Weile, um meinen Vorsprung weiter zu machen. Aber das sieht aus wie ich brauche! – yiwei

+0

@Andreas meine 'getName()'/'PageDetail' ist nicht endgültig, aber' p' ist garantiert keine Unterklasse von 'PageDetail. Also sollte das noch funktionieren, oder? – yiwei

+0

Ich mag diese Antwort nicht, denn wenn PageDetail mehr als 2 Felder (displayName und Beschreibung) enthält, haben Sie viele map() .oderElse-Aufrufe. Ich bevorzuge eine Fallback-Instanz und arbeite mit einer nicht-optionalen Instanz von dort. – pyb

8

Verwenden Optional#orElseGet, die eine Supplier nimmt:

// 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 eine leere PageDetail schaffen nur, wenn das optionale einen Nullwert hat. Dies hält Ihre Code-Ressource effizient.

Editierbare/übersetzbar Beispiel: https://ideone.com/9h1Ntg

Edit: Vielen Dank allen für das Feedback! Ich habe tatsächlich orElseGet hinzugefügt, die ich besser finde. Ich reparierte auch den Code, um die Optional auszupacken, also pageDetail Enden, die eine tatsächliche PageDetail Instanz sind.

Bearbeiten 2: Hinzugefügt verschiedene Syntax Beispiel und bearbeitbare/kompilierbare Beispiel.

+2

Nein, das ist falsch, weil Sie 'getName()' aufrufen müssen, um den Anzeigenamen zu erhalten. – Tunaki

+0

oderElse (T andere), nicht oderElseGet (Lieferant andere) – leoger

+0

@Tunaki, verstehe ich nicht Ihren Kommentar. Könntest Du das erläutern? – leoger

Verwandte Themen