Tech up! Java 9 Optionals

Wir möchten uns heute in unserer Serie “Java 9 Perlen” die Erweiterungen in der Optional Klasse etwas genauer anschauen.

Obwohl es in Java keine expliziten Pointer gibt, hat man als Entwickler täglich mit Nullpointer Exceptions zu kämpfen. Seit Java 8 gibt es die (generische) Klasse Optional, die einen möglichen Wert kapselt: Falls der Wert vorhanden ist, enthält Optional den Wert, andernfalls ist das Optional “empty”.

Um das zu verdeutlichen, starten wir mit einer Klasse NameConverter, die einen männlichen Vornamen in einen weiblichen konvertiert. Die toFemale() Methode gibt ein Optional zurück, welches den konvertierten Vornamen oder empty enthält (falls kein Vorname gefunden wurde). Das Ganze ist mit einer simplen Map<String, String> implementiert, welche wir mittels der (in Java 9 neuen) Collections Factory Methods erstellen. Die Implementation von toFemale() ist dann mittels Optional.ofNullable() ein Einzeiler.

Wir implementieren eine weitere Methode toFemale(), die als Parameter eine Liste von Vornamen nimmt und als Resultat eine Liste von Optional<String> zurückgibt, die jeweils den konvertierten Namen oder empty enthält.

Basierend auf diesem Beispiel möchten wir uns nun die Erweiterungen in Java 9 anschauen.

stream() – Extrahieren von nicht empty Werten

API

public Stream<T> stream() 

If a value is present, returns a sequential {@link Stream} containing only that value, otherwise returns an empty {@code Stream}.

Wenn wir an toFemale() eine Liste von Vornamen übergeben, bekommen wir als Resultat eine Liste von Optionals zurück. Wir möchten nun aus diesem Resultat alle nicht emptyWerte extrahieren. In Java 8 kann man dies in 2 Schritten erreichen:

  • Zuerst werden die empty Werte mittels Optional.isPresent () herausgefiltert
  • In einem zweiten Schritt den Wert aus dem Optional mittels Optional.get() extrahiert

In Java 9 gibt es auf dem Optional eine neue Methode stream(), mit der man filter und map in einer Anweisung kombinieren kann:

Da stream() selbst einen Stream<T> zurückgibt, muss man flatMap() statt map() verwenden.

ifPresentOrElse() – Optional Wert oder empty verarbeiten

API

public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)

If a value is present, performs the given action with the value otherwise performsthe given empty-based action.

Als Nächstes möchten wir mittels toFemale() einen einzelnen Vornamen übersetzten, und je nachdem ob das geklappt hat, das Ergebnis verarbeiten. In Java 8 kann man diesmittels Optional.isPresent(), Optional.get() und einem normalen if/else implementieren:

In Java 9 kann man dies mittels Optional.ifPresentOrElse() implementieren. Dazu hat die Methode folgende Parameter:

  • Consumer<? super T> action: action wird ausgeführt, wenn das Optional einen Wert hat
  • Runnable emptyAction: emptyAction wird ausgeführt falls das Optional empty ist

In Java 9 kann man die gewünschte Funktionalität in einer einzigen Anweisung implementieren:

or() – alternatives Optional berechnen wenn Optional empty ist

API

public Optional<T> or( Supplier<? extends Optional<? extends T>> supplier )

If a value is present, returns an {@code Optional} describing the value, otherwise returns an {@code Optional} produced by the supplying function.

Optional.or() gibt das Optional selbst zurück, falls es einen Wert enthält. Fall das Optional empty ist, wird ein neues Optional zurückgegeben, welches mittels eines Suppliers erstellt wird.

Dazu ein kleines Beispiel: Wir lassen mittels toFemale() einen Vornamen konvertieren. Falls die Konvertierung erfolgreich war, wird im Optional der weibliche Vorname stehen. Falls die Konvertierung nicht erfolgreich war, gibt toFemale() ein empty zurück. In diesem Fall möchten wir empty in ein neues Optional mit der Info “no translation” umwandeln und dieses Optional zurückgeben. Genau diesen Mechanismus ist in Optional.or() implementiert:

Ausgabe: Franz – > Franziska

Ausgabe: Peter – > no translation

So viel zum Thema Optionals und Java 9. Im nächsten Blog Artikel werden wir uns die Erweiterungen im Stream API anschauen.

Kommentare sind geschlossen.