{"id":2638,"date":"2014-01-10T17:19:36","date_gmt":"2014-01-10T15:19:36","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=2638"},"modified":"2014-01-10T17:19:36","modified_gmt":"2014-01-10T15:19:36","slug":"map-methoden-von-optional-fr-funktionale-programmierung","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2014\/01\/map-methoden-von-optional-fr-funktionale-programmierung\/","title":{"rendered":"map(&hellip;) Methoden von Optional f&uuml;r funktionale Programmierung"},"content":{"rendered":"<p>Java 8 bekommt eine Optional Klasse und die beiden XXXmap(\u2026)-Methoden sind besonders interessant. Sie erm\u00f6glichen einen ganz neuen Programmierstil. Warum soll ein Beispiel zeigen. <\/p>\n<p>Der folgende Zweizeiler gibt auf meinem System \u201eMICROSOFT KERNELDEBUGGER-NETZWERKADAPTER\u201c aus: <\/p>\n<p>String s = NetworkInterface.getByIndex( 2 ).getDisplayName().toUpperCase(); <\/p>\n<p>System.out.println( s ); <\/p>\n<p>Allerdings ist der Programmcode alles andere als gut, denn NetworkInterface.getByIndex(int) kann null zur\u00fcckgeben und getDisplayName() auch. Um ohne eine NullPointerException um die Klippen zu schiffen m\u00fcssen wir schreiben: <\/p>\n<p>NetworkInterface networkInterface = NetworkInterface.getByIndex( 2 ); <\/p>\n<p>if ( networkInterface != null ) { <\/p>\n<p>String displayName = networkInterface.getDisplayName(); <\/p>\n<p>if ( displayName != null ) <\/p>\n<p>System.out.println( displayName.toUpperCase() ); <\/p>\n<p>} <\/p>\n<p>Von der Eleganz des Zweizeilers ist nicht mehr viel geblieben. Integrieren wir Optional (was ja eigentlich ein toller R\u00fcckgabetyp f\u00fcr getByIndex() und getDisplayName(): <\/p>\n<p>Optional&lt;NetworkInterface&gt; networkInterface = Optional.ofNullable( NetworkInterface.getByIndex( 2 ) ); <\/p>\n<p>if ( networkInterface.isPresent() ) { <\/p>\n<p>Optional&lt;String&gt; name = Optional.ofNullable( networkInterface.get().getDisplayName() ); <\/p>\n<p>if ( name.isPresent() ) <\/p>\n<p>System.out.println( name.get().toUpperCase() ); <\/p>\n<p>} <\/p>\n<p>Mit Optional wird es nicht sofort besser, doch statt if k\u00f6nnen wir ein Lambda-Ausdruck einsetzen und bei ifPresent(\u2026) einsetzen: <\/p>\n<p>Optional&lt;NetworkInterface&gt; networkInterface = Optional.ofNullable( NetworkInterface.getByIndex( 2 ) ); <\/p>\n<p>networkInterface.ifPresent( ni -&gt; { <\/p>\n<p>Optional&lt;String&gt; displayName = Optional.ofNullable( ni.getDisplayName() ); <\/p>\n<p>displayName.ifPresent( name -&gt; { <\/p>\n<p>System.out.println( name.get().toUpperCase() ); <\/p>\n<p>} ); <\/p>\n<p>} ); <\/p>\n<p>Wenn wir nun die lokale Variablen entfernen, kommen wir aus bei: <\/p>\n<p>Optional.ofNullable( NetworkInterface.getByIndex( 2 ) ).ifPresent( ni -&gt; { <\/p>\n<p>Optional.ofNullable( ni.getDisplayName() ).ifPresent( name -&gt; { <\/p>\n<p>System.out.println( name.get().toUpperCase() ); <\/p>\n<p>} ); <\/p>\n<p>} ); <\/p>\n<p>Von der Struktur ist das mit der if-Afrage identisch und \u00fcber die Einr\u00fcckungen auch zu erkennen. Fallunterscheidungen mit Optional und ifPresent(\u2026) umzuschreiben bringt also keinen Vorteil. <\/p>\n<p>In Fallunterscheidungen zu denken hilft hier nicht weiter. Was wir uns bei NetworkInterface.getByIndex( 2 ).getDisplayName().toUpperCase() vor Augen halten m\u00fcssen ist eine Kette von Abbildungen. NetworkInterface.getByIndex(int) bildet auf NetworkInterface ab, getDisplayName() von NetworkInterface bildet auf String ab, und toUpperCase()bildet von einem String auf einen anderen String ab. Wir verketten also drei Abbildungen und m\u00fcssten ausdr\u00fccken k\u00f6nnen: Wenn eine Abbildung fehlschl\u00e4gt, dann h\u00f6re mit der Abbildung auf. Und genau hier kommt Optional und map(\u2026) ins Spiel. In Code: <\/p>\n<p>Optional&lt;String&gt; s = Optional.ofNullable( NetworkInterface.getByIndex( 2 ) ) <\/p>\n<p>. map( ni -&gt; ni.getDisplayName() ) <\/p>\n<p>. map( name -&gt; name.toUpperCase() ); <\/p>\n<p>s.ifPresent( System.out::println ); <\/p>\n<p>Die Klasse Optional hilft uns bei zwei Dingen: Erstes wird map(\u2026) beim Empfangen einer null-Referenz auf ein Optional.empty() abbilden. Und zweitens ist das Verketten von leeren Optionals kein Problem, es passiert einfach nichts \u2013 Optional.empty().map(\u2026) f\u00fchrt nichts aus und die R\u00fcckgabe ist einfach nur ein leeres Optional. <\/p>\n<p>Umgeschrieben mit Methoden-Referenzen und weiter verk\u00fcrzt ist das Code sehr gut lesbar. <\/p>\n<p>Optional.ofNullable( NetworkInterface.getByIndex( 2 ) ) <\/p>\n<p>. map( NetworkInterface::getDisplayName ) <\/p>\n<p>. map( String::toUpperCase ) <\/p>\n<p>.ifPresent( System.out::println ); <\/p>\n<p>Die Logik kommt ohne externe Fallunterscheidungen aus und arbeitet nur mit optionalen Abbildungen. Das ist ein sch\u00f6nes Beispiel f\u00fcr funktionale Programmierung.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Java 8 bekommt eine Optional Klasse und die beiden XXXmap(\u2026)-Methoden sind besonders interessant. Sie erm\u00f6glichen einen ganz neuen Programmierstil. Warum soll ein Beispiel zeigen. Der folgende Zweizeiler gibt auf meinem System \u201eMICROSOFT KERNELDEBUGGER-NETZWERKADAPTER\u201c aus: String s = NetworkInterface.getByIndex( 2 ).getDisplayName().toUpperCase(); System.out.println( s ); Allerdings ist der Programmcode alles andere als gut, denn NetworkInterface.getByIndex(int) kann null [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[11,66],"tags":[],"class_list":["post-2638","post","type-post","status-publish","format-standard","hentry","category-insel","category-java-8"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2638","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=2638"}],"version-history":[{"count":1,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2638\/revisions"}],"predecessor-version":[{"id":2639,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/2638\/revisions\/2639"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=2638"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=2638"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=2638"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}