Java 8 – Lambda Expressions

Mit Java 8 halten Lambda Expressions Einzug in die Java Welt. Ein Lambda Ausdruck umfasst dabei Funktionalität, die nicht benannt (eine eigene Methode) oder einer Klasse zugeordnet ist, sondern Code der gespeichert und ausgeführt werden kann. Dabei werden Lambdas wie Argumente an Operationen übergeben, die die Funktionalität später ausführen. Ein viel zitiertes Beispiel aus der Stream API (auch eine Neuerung in Java 8) ist:

Stream.of(1,2,3,4,5).forEach({x –> System.out.print(x)})

Dabei wendet die forEach Methode die Lambda Expression an jedem Element der Sequenz an.

x –> System.out.print(x) ist der Lambda Ausdruck. Erst hat er wie eine Methode eine Parameterliste (in diesem Falle nur x). Diese wird mit einem Pfeilsymbol –> an einen geklammerten Lambda-Body übergeben. Wie bei einer anonymen Klasse fehlt der Methodenname. Returntype und eventuelle throws Klausel deduziert der Compiler automatisch aus dem Lambda-Body.

Warum?

Das mag am Anfang etwas befremdlich aussehen. Der Vorteil erschließt sich einem jedoch, wenn man die weiteren neuen Sprachkonstrukte wie

  • default Methoden in Interfaces,
  • @FunctionalInterface
  • oder aber die neue Stream API
  • Methodenreferenzen

hinzuzieht.

Ich möchte das Anhand eines Beispiels illustrieren. Seit Java 1.5 möchte man den extended for loop nicht mehr missen um über die Elemente einer Collection zu iterieren

List<String> foobarList = Arrays.asList("foo","bar","foobar");
for (String foo : myList) {
  System.out.println(foo);
}

Eigentlich schön kurz und übersichtlich, jedoch ist die Umsetzung der Iteration an den Ort des Aufrufes gebunden. Auch kann der extended for loop nicht für eine Paralellisierung herangezogen werden. Dazu müsste man die Liste vorerst in kleinere Teillisten zerlegen und diese dann in unterschiedlichen Threads abarbeiten. Natürlich könnte man sich dafür wieder eine Util Klasse schreiben oder sich eine bereits vorhandene Lösung suchen. Aber es wäre schon schön wenn man das einfach der List überalssen könnte. Zu diesem Zweck wurden default Methoden in Interfaces eingeführt und das Iterable Interface mit einer forEach(Consumer<? superT> action) Methode erweitert.

foobarList.forEach(new Consumer<String>() {
   public void accept(String foo) {
      System.out.println(foo);
   }
});

Der Code hat dabei zwar an Länge zugelegt, aber es hat auch noch die Übersichtlichkeit darunter gelitten. Großes Plus dabei ist natürlich die saubere Trennung von Logik für die Iteration von der Logik für die Verarbeitung des einzelnen Elements. Parallelisierung wir kommen!

Aber es steckt schon eine Menge unübersichtlicher Boilerplate-Code drum herum. Verpacken wir das nun jedoch in die Lambda-Notation habe wir ein übersichtliches Stück Code:

foobarList.forEach((String foo) -> System.out.println(foo));

In diesem speziellen Fall lässt sich der Code noch auf ein Minimum reduzieren, da er nur einen einzelnen Parameter hat und wir sogenannte Methodenreferenzen nutzen können. Diese sind ebenfalls mit Java 8 und den Lambda Ausdrücken im Sprachraum Java eingeführt worden.

myList.forEach(System.out::print);

Nice!

Weiterführende Literatur

Die von Oracle angedachten Anwendungsbereiche sowie eine ausführliche Einführung findet man unter http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

Wer sich lieber berieseln lassen mag, dem seien die Videos der Oracle Learning Library empfohlen. Hier das kurze Teaser Video dazu:

Ähnliche Artikel:

Java 8 – Functional Interfaces

Java 8 bereichert das Java um Functional Interfaces. Ein Interface ist genau dann ein Functional Interface wenn es nur eine abstrakte Methode definiert.

Java 8 bereichert das Java Universum um Functional Interfaces. Ein Interface ist genau dann ein Functional Interface wenn es nur eine abstrakte Methode definiert. Ein populäres Beispiel dafür ist java.lang.Runnable da es lediglich

void run();

als abstrakte Methode definiert. Das funktionale Interface wird in weiterer Folge benötigt, um Lambda Ausdrücke, Methodenreferenzen und Klassenreferenzen nutzen zu können. Dazu hier im Blog bald mehr.

Um ein Interface bewusst als funktionales Interface zu kennzeichnen gibt es, seit Java 8, die neue Annotation @FunctionalInterface. Ein Interface mit dieser Annotation wirft beim Kompilieren einen Fehle, wenn es die Voraussetzungen dafür nicht erfüllt.

Ein funktionales Interface darf zwar nur eine abstrakte Methode definieren, kann jedoch beliebig viele default und static Methoden (siehe meinen Blogpost Java 8 – Erweiterungen rund ums Interface) führen.

Ähnliche Artikel:

Java 7 Tage Überblick – Was kommt dannach? Java 8

Java 7 haben wir in den vorherigen Blogeinträgen angesehen, was noch angedacht war und vielleicht bald in Java 8 zu sehen ist wird in diesem Artikel erläutert.

Ich weiß die Überschrift dieses Eintrags ist wenig kreativ, aber sein wir uns ehrlich, es war eh schon allen klar, nach der 7 kommt die 8. Chromo machts vor, auch Firefox steigt auf den Highway der Versionsnummernvergabe und nachdem Java nun 5 Jahre still stand möchte Oracle die Programmiersprache in einen Schnellzug verwandeln. Bereits Ende 2012 will man mit Java 8 JSRs nachreichen, die sich zeitlich nicht mehr in dieses Release unterbringen liesen.

Darunter fallen folgende JSRs:

  • JSR 294: Language and VM support for modular programming
  • JSR 308: Annotations on Java types
  • JSR TBD: Language support for collections
  • JSR TBD: Project Lambda
  • Modularization (Project Jigsaw)
  • JSR 296: Swing application framework
  • Swing JDatePicker component

Dabei ist ausdrücklich vermerkt, dass nicht alle der aufgeführten Punkte fix einen Platz in Java 8 haben werden. Was dabei auf uns zukommt sei nun kurz zu jedem der Punkte erklärt:

JSR 294: Language and VM support for modular programming

Der JSR 294 soll Sprach und VM Features beinhalten um modulares Programmieren zu ermöglichen/erleichtern indem es standardisierte Möglichkeiten für das Zugreifen auf Module bieten soll. Dies soll modularen Systemen wie OSGI und Jigsaw zugute kommen können. Nähere Detail unter http://jcp.org/en/jsr/detail?id=294 Ein guter Blog Eintrag der das den Bereich auf den JSR 294 abzielt erklärt ist auf blog.bjhargrave.com zu finden (in Englisch).

JSR 308: Annotations on Java types

Dieser JSR befasst isch mit einer Erweiterung der Verwendbarkeit von Annotationen. Bisher konnte man nur Packages, Typen, Methoden und Konstruktoren, Felder, lokale Variablen, Methodenparameter und Enumeratoren mit Annotationen versehen. Dies soll nun soweit erweitert werden, dass Annotationen überall dort Verwendung finden können, wo Typen erlaubt sind. Man kann nun zB dei Typangaben einer Map eine Annotation anhängen.

Map<@NunNull String, Integer> map;

Mehr dazu hier.

JSR TBD: Language support for collections

Dieser Teil wurde aus Project Coin herausgenommen und auf das nächste Release verschoben. Er beinhaltet eine erweiterte Sprachunterstützung für Collections, die dem Entwickler den Umgang damit erleichtern sollen. Wie die Implementierung dazu genau aussehen wird weiß ich noch nicht, ich möchte daher auf die Mailing Liste von Project Coin verweisen, wo man näheres in Erfahrung bringen könnte.

JSR TBD: Project Lambda

Vor einiger Zeit noch unter dem Namen „Closures“ wild diskutiert, versteckt sich hinter Project Lambda. Dahinter verbirgt sich die Möglichkeit Funktionsaufrufe als Parameter zu übergeben. Ein schnelles Beispiel, anstatt eine Runnable instanzieren zu müssen, soll man den inhalt der Runnable#run() Methode direkt übergeben können:

new Thread(#{System.out.println("Nullpointer!")}).start();

Dies ist ein stark vereinfachtes Beispiel, dass ich von folgendem Artikel aus jaxenter übernommen habe. Weitere Information gibts dort, oder aber direkt auf der Projekthomepage.

Modularization (Project Jigsaw)

Während JSR 294 für die Modularisierung unterstützend sein soll, wird in Project Jigsaw der Stier bei den Hörnern gepackt. Zwar kann man in Java aktuell Klassen zu Paketen zusammenfassen und hat damit einzeln gruppierte „Module“, doch es ist dabei nirgends definiert, was so ein Modul anderen Modulen an Funktionalität zur Verfügung stellt, welche es selbst benötigt, und in welchen Versionen. Letzteres ist zum Teil in Build Tools wie Maven abgebildet, jedoch kann lediglich eine Version des Jars eingebunden werden. Was wenn eine andere Bibliothek eine andere Version desselben Jar Files benötigt? Dieses Problem kann mit Project Jigsaw in Java 8 angegangen werden. Andere Lösungen wie z.B. OSGi (Open Service Gateway Initiative) wären ebenfalls eine Variante, Project Jigsaw soll jedoch mit dem JDK freihaus mitgeliefert werden.

JSR 296: Swing application framework

Hierzu habe ich leider nicht viel gefunden, die JSR Seite ist recht spärlich befüllt. Es soll erreicht werden, dass das Erstellen von Swing Anwendungen vereinfacht wird indem für Standardelemente ein Framework geschaffen wird, dass zB Startup, Shutdown, Resourcenmanagement oder Action- bzw. Session Statemanagement vereinfacht.

Swing JDatePicker component

Eigentlich sowas wie eine Standardkomponente, dennoch nicht im Java Core integriert, ein Date Picker! Zur Ehrenrettung von Java wurde in SwingX eine entsprechende Componente geschaffen, die bald ins Standardrepatoire übernommen werden könnte. Wie diese Komponente aussieht findet ihr hier und hier gibts die API dazu.

Nicht auf der Featureseite von Java 7 für kommende Versionen vermerkt, aber dennoch eine interessante und auch notwendige Neuerung die da bald kommen könnte:

JSR 310: Date and Time API

Ziel davon ist es eine neue simplere API zu schaffen um mit Zeiten und verschiedenen Daten umgehen zu können. Eine Referenzimplementierung dazu schafft das Sourceforge Projekt ThreeTen. Da das Projekt sich noch in der Alpha Phase befindet sei zumindest auf den UserGuide verwiesen, der die Funktionalität in grundzügen erklärt.

So, da darf man schonmal gespannt sein, doch bis es soweit ist, viel Spaß mit Java 7!

Ähnliche Artikel: