Kleiner Optional-Trick in Java


So froh ich über die Einführung von Optional in Java 8 bin, so ärgerlich ist dort das Fehlen von Methoden, die eigentlich selbstverständlich sein sollten. So renne ich öfter in die Situation, dass ich aus dem Optional keinen Wert zurückliefern möchte, sondern abschließend eine Aktion ausführen. Dafür gibt es die Methode ifPresent, die einen Consumer entgegennimmt. Das Problem ist, dass ich im Falle eines leeren Optionals keine Default-Aktion angeben kann.

Zur Veranschaulichung ein Beispiel: Ich möchte aus einem Integer-Optional heraus auf die Konsole schreiben, ob die Zahl gerade ist oder nicht. Ist das Optional leer, will ich auch das auf die Konsole schreiben. Natürlich würde man in diesem einfachen Fall normalerweise den String „durchreichen“, aber nehmen wir an, dass statt der Textausgabe verschiedene Aktionen erforderlich sind, die sich nicht so leicht „integrieren“ lassen. Gewöhnlich sah der Code dann bei mir so aus:

Optional<Integer> op = ...
if (op.isPresent()) {
    op.ifPresent(i -> {
        System.out.println(i % 2 == 0 ? "even" : "odd");
    });
} else {
    System.out.println("empty");
}

Ich finde den expliziten Test recht hässlich – eine zusätzliche Schleife, die unser Gehirn drehen muss. Mein Workaround wird sicher auch keinen Schönheitspreis gewinnen, trotzdem halte ich diese Version für einen (kleinen) Fortschritt:

Optional<Integer> op = ...
op.<Runnable>map(i -> () -> {
    System.out.println(i % 2 == 0 ? "even" : "odd");
}).orElse(() -> System.out.println("empty")
).run();

Der Trick ist, die Aktion nicht sofort auszuführen, sondern in ein Runnable zu verpacken. Damit kann man dieses als Wert „durchschleifen“, und hat damit auch die Chance, über orElse auch einen Defaultwert angeben zu können. Die generische Typangabe bei map ist leider notwendig, und die Schreibweise mit den zwei Pfeilen in map ist auch gewöhnungsbedürftig. Man muss auch aufpassen, dass man das run() am Ende nicht vergisst.

Ich hoffe wirklich, dass hier bei Java 9 noch nachgebessert wird, denn solche Klimmzüge für ein einfaches Problem müssen nun wirklich nicht sein. Oder habe ich eine elegantere Lösung übersehen?

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s