-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlambda-ausdruecke.html
18 lines (17 loc) · 14.6 KB
/
lambda-ausdruecke.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html><html lang="de-ch"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Lambda-Ausdrücke Teil 1 - Finecloud</title><meta name="description" content="Seit Java 8 können mit Lambda Expressions Funktionen komfortabler, kürzer und lesbarer ausgedrückt werden. Nachfolgend ein Beispiel von Java Code. Dieses Stück Code sucht aus Ihrer Musiksammlung die 100 längsten Songs heraus, die Sie mit mehr als vier Sternen bewertet haben und deren Interpret Ihnen…"><meta name="generator" content="Publii Open-Source CMS for Static Site"><link rel="stylesheet" href="https://www.finecloud.ch/media/plugins/syntaxHighlighter/prism-black.css"><link rel="canonical" href="https://www.finecloud.ch/lambda-ausdruecke.html"><link rel="alternate" type="application/atom+xml" href="https://www.finecloud.ch/feed.xml"><link rel="alternate" type="application/json" href="https://www.finecloud.ch/feed.json"><meta property="og:title" content="Lambda-Ausdrücke Teil 1"><meta property="og:site_name" content="Finecloud"><meta property="og:description" content="Seit Java 8 können mit Lambda Expressions Funktionen komfortabler, kürzer und lesbarer ausgedrückt werden. Nachfolgend ein Beispiel von Java Code. Dieses Stück Code sucht aus Ihrer Musiksammlung die 100 längsten Songs heraus, die Sie mit mehr als vier Sternen bewertet haben und deren Interpret Ihnen…"><meta property="og:url" content="https://www.finecloud.ch/lambda-ausdruecke.html"><meta property="og:type" content="article"><link rel="shortcut icon" href="https://www.finecloud.ch/media/website/finecloud.png" type="image/png"><link rel="stylesheet" href="https://www.finecloud.ch/assets/css/style.css?v=39da73365516a098a9b73b721fc970e2"><script type="application/ld+json">{"@context":"http://schema.org","@type":"Article","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.finecloud.ch/lambda-ausdruecke.html"},"headline":"Lambda-Ausdrücke Teil 1","datePublished":"2022-05-29T09:56","dateModified":"2022-07-02T07:39","description":"Seit Java 8 können mit Lambda Expressions Funktionen komfortabler, kürzer und lesbarer ausgedrückt werden. Nachfolgend ein Beispiel von Java Code. Dieses Stück Code sucht aus Ihrer Musiksammlung die 100 längsten Songs heraus, die Sie mit mehr als vier Sternen bewertet haben und deren Interpret Ihnen…","author":{"@type":"Person","name":"Finecloud","url":"https://www.finecloud.ch/authors/finecloud/"},"publisher":{"@type":"Organization","name":"Finecloud"}}</script><meta name="google-site-verification" content="seFY9U12uiEq5U3_MyZiX6XWzk0AVFl9zITr2ZKsytY"></head><body><div class="site-container"><header class="top" id="js-header"><a class="logo" href="https://www.finecloud.ch/">Finecloud</a><nav class="navbar js-navbar"><button class="navbar__toggle js-toggle" aria-label="Menu" aria-haspopup="true" aria-expanded="false"><span class="navbar__toggle-box"><span class="navbar__toggle-inner">Menu</span></span></button><ul class="navbar__menu"><li><a href="https://www.finecloud.ch/" target="_self">Blog</a></li><li><a href="https://www.finecloud.ch/tags/" target="_self">Tags</a></li></ul></nav><div class="search"><div class="search__overlay js-search-overlay"><div class="search__overlay-inner"><form action="https://www.finecloud.ch/search.html" class="search__form"><input class="search__input js-search-input" type="search" name="q" placeholder="search..." aria-label="search..." autofocus="autofocus"></form><button class="search__close js-search-close" aria-label="Close">Close</button></div></div><button class="search__btn js-search-btn" aria-label="Search"><svg role="presentation" focusable="false"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#search"/></svg></button></div></header><main><article class="post"><div class="hero"><figure class="hero__image hero__image--overlay"><img src="https://www.finecloud.ch/media/website/download.jpg" srcset="https://www.finecloud.ch/media/website/responsive/download-xs.jpg 300w, https://www.finecloud.ch/media/website/responsive/download-sm.jpg 480w, https://www.finecloud.ch/media/website/responsive/download-md.jpg 768w, https://www.finecloud.ch/media/website/responsive/download-lg.jpg 1024w, https://www.finecloud.ch/media/website/responsive/download-xl.jpg 1360w, https://www.finecloud.ch/media/website/responsive/download-2xl.jpg 1600w" sizes="100vw" loading="eager" alt=""></figure><header class="hero__content"><div class="wrapper"><div class="post__meta"><time datetime="2022-05-29T09:56">Mai 29, 2022</time></div><h1>Lambda-Ausdrücke Teil 1</h1></div></header></div><div class="wrapper post__entry"><div class="post__toc"><h3>Table of Contents</h3><ul><li><a href="#mcetoc_1g4tduort5q2">Was sind Lambda-Ausdrücke?</a></li><li><a href="#mcetoc_1g4tduort5q3">Die Lambda-Syntax</a></li><li><a href="#mcetoc_1g4tduort5q4">Methodenreferenz</a></li></ul></div><p>Seit Java 8 können mit Lambda Expressions Funktionen komfortabler, kürzer und lesbarer ausgedrückt werden.</p><p>Nachfolgend ein Beispiel von Java Code. Dieses Stück Code sucht aus Ihrer Musiksammlung die 100 längsten Songs heraus, die Sie mit mehr als vier Sternen bewertet haben und deren Interpret Ihnen nicht bekannt ist, und berechnet die Gesamtlänge dieser Songs:</p><p><code>List<Song> songs = …;</code><br><code>int sekunden = 0;</code><br><code>Sekunden</code><br><code>Collections.sort(songs, new Comparator<Song>(){</code><br><code> @Override</code><br><code> public int compare(Song o1, Song o2) {</code><br><code> return o1.getLaengeInSekunden() - o2. getLaengeInSekunden ();</code><br><code> }</code><br><code>});</code><br><code>int zaehler = 0;</code><br><code>for (Song song : songs){</code><br><code> if (song.getSterne() > 4 </code><br><code> && ("Unbekannter Künstler".equals(song.getInterpret())){</code><br><code> sekunden += song.getLaengeInSekunden();</code><code></code><br><code> if (++zaehler > 100) break;</code><br><code> }</code><br><code>}</code></p><p>Nachfolgend der Java Code der den gleichen Zweck erfüllt, aber Lambda Ausdrücke verwendet:</p><p><code>int sekunden = songs.stream()</code><br><code> .filter(song -> "Unbekannter Künstler".equals(song.getInterpret()))</code><br><code> .filter(song -> song.getSterne() > 4)</code><br><code> .sorted(Comparator.comparing(Song::getLaengeInSekunden).reversed())</code><br><code> .limit(100)</code><br><code> .mapToInt(Song::getLaengeInSekunden)</code><br><code> .sum();</code></p><p>Die Vorteile liegen auf der Hand: Abgesehen von der Zeilen und Codelänge ist der Code auch viel einfach verständlich, schnell lässt sich erkennen, was der Code bewirkt. In den ersten beiden Zeilen wird die Liste gefiltert (filter), danach sortiert (sorted), auf die 100 ersten Ergebnisse beschränkt (limit), jeder Song auf sein int-Feld laengeInSekunden abgebildet (mapToInt) und von den Längen schliesslich die Summe (sum) berechnet</p><h3 id="mcetoc_1g4tduort5q2">Was sind Lambda-Ausdrücke?</h3><p>Es handelt sich dabei um Javas Sprachmittel, um Funktionen auszudrücken, im Gegensatz dazu stehen die prozedualen Konstrukte wie Verzweigungen und Schleifen, mit denen der Programmierablauf dargestellt wird. Lambda-Ausdrücke erlauben es zusammen mit entsprechenden APIs im Code nur das Wesentliche zu schreiben, ohne dabei jedes Mal das Übliche wiederholen zu müssen. Das Wesentliche ist eine Liste von Songs zu filtern. Das Übliche wäre in diesem Fall, über eine Liste zu iterieren und jedes Element zu prüfen.</p><p>Ohne Lambda-Ausdrücke wird der Code länger, wenige gut lesbar und Fehleranfälliger, denn in Schleifen und Prüfungen schleichen sich gerne Fehler ein.</p><h3 id="mcetoc_1g4tduort5q3">Die Lambda-Syntax</h3><p>Lambda-Ausdrücke sind auf den ersten Blick als solche erkennbar durch den Pfeil ->, der vorkommen muss und in Java keine andere Bedeutung hat.</p><p><code>(Song song) -> {</code><br><code> return "Unbekannter Künstler".equals(song.getInterpret());</code><br><code>}</code></p><p>Links vom Pfeil stehen die Parameter und rechts vom Pfeil steht, was mit diesen parametern geschehen soll. Mehrere Parameter werden, genau wie bei einer Methodendeklaration auch durch Kommas getrennt.</p><p>Doch es geht noch kürzer. Es dürfen auch die Parametertypen wegfallen:</p><p><code>(song) -> {</code><br><code> return "Unbekannter Künstler".equals(song.getInterpret());</code><br><code>}</code></p><p>Der Java-Compiler ist inzwischen sehr gut darin, Typen aus dem Kontext zu erkennen. Da wir mit einer List<Song> arbeiten und daraus ein Stream<Song> wird, ist für den Compiler klar, dass der Typ des Rückgabewerts auch ein Song sein muss.</p><p>Weiter darf, wenn der Lambda-Ausdruck nur ein Parameter benötigt die Klammer um den Parameter herum entfallen:</p><p><code>song -> {</code><br><code> return "Unbekannter Künstler".equals(song.getInterpret());</code><br><code>}</code></p><p>Wenn der Ausdruck allerdings keine Parameter hat, muss die Klammer wieder hin. Beispielsweise kann () -> 3 ein gültiger Lambda-Ausdruck sein, der keine Parameter erwartet und die Zahl 3 zurückgibt.</p><p>Als letzte Verkürzungsregel darf, wenn ein Rumpf eines Ausdrucks nur aus einem Ausdruck besteht, also einer einzigen Anweisung, die zu einem Wert ausgewertet wird (Vergleich, Berechnung oder Methodenaufruf) nur der Wert-Ausdruck selbst angegeben werden, ohne geschweifte Klammern, ohne Semikolon und ohne return:</p><p><code>song -> "Unbekannter Künstler".equals(song.getInterpret())</code></p><p>Dabei gibt es aber keine Zwischenschritte, entweder man gibt den Ausdruck wie im letzten Beispiel an, oder man muss den Ausdruck mit geschweiften Klammern, Semikolon und return angeben. Natürlich ist die kürzeste Version anzustreben. Deshalb sollte immer auf die Blockschreibweise verzichtet werden, ausser man hat mehr als ein Wert-Ausdruck, beispielsweise bei einem if-Statement, hier müssen die äusseren Klammern und Returns geschrieben werden:</p><p><code>(s1, s2) -> {</code><br><code> if (aufsteigend){</code><br><code> return s1.getLaengeInSekunden() - s2.getLaengeInSekunden();</code><br><code> } else {</code><br><code> return s2.getLaengeInSekunden() - s1.getLaengeInSekunden();</code><br><code> }</code><br><code>}</code></p><p>Als letzte Spezialität in diesem Artikel gehe ich auf die Variable aufsteigend ein. Genau wie anonyme innere Klassen können Lambdas auf lokale Variablen ihrer Umgebung zugreifen. Diese lokalen Variablen müssen nicht als final deklariert werden, müssen aber also solche behandelt werden. Das heisst, es reicht aus wenn ihnen im Lambda-Ausdruck oder danach kein neuer Wert mehr zugewiesen wird.</p><h3 id="mcetoc_1g4tduort5q4">Methodenreferenz</h3><p>Wenn ein Lambda-Ausdruck nur am einzigen übergebenen Parameter eine Methode aufruft und deren Rückgabewert weitergibt, dann kann statt des Lambda-Ausdrucks eine Methodenreferenz angeben werden. Die nachfolgenden Aufrufe haben die gleiche Wirkung:</p><p><code>Comparator.comparing(song -> song.getSterne());</code><br><code>Comparator.comparing(Song::getSterne);</code></p><p>Methodenreferenzen erkennt man am doppelten Doppelpunkt. Davor steht die Klasse, dahinter die Methode. Wichtig ist, dass man bei der Methodenreferenz keine Klammern nach dem Methodenamen setzt. Das Beispiel von oben ist eine <em>ungebundene Referenz</em>: Sie bezeichnet nicht die getSterne-Methode eines bestimmten Objekts, sondern kann auf beliebige Objekte der Klasse Song angewendet werden. Ist vor dem doppelten Doppelpunkt keine Klasse, sondern eine Objektreferenz, dann ist die Methodenreferenz gebunden und meint immer die Methode dieses einen Objekts.</p><p><code>Musicplayer player = new Musicplayer();</code><br><code>songs</code><br><code> .filter(s -> s. getSterne() == 5)</code><br><code> .forEach(player::play);</code></p><p>Die Referenz player::play meint immer die play-Methode des Musicplayer, den die Variable player referenziert. Mit Lambda-Ausdrücken, aber ohne Methodenreferenz, sähe das Beispiel dann so aus:</p><p><code>Musicplayer player = new Musicplayer();</code><br><code>songs</code><br><code> .filter(s -> s. getSterne() == 5)</code><br><code> .forEach(s -> player.play(s));</code></p></div><footer class="wrapper post__footer"><p class="post__last-updated">This article was updated on Juli 2, 2022</p><ul class="post__tag"><li><a href="https://www.finecloud.ch/tags/java/">java</a></li><li><a href="https://www.finecloud.ch/tags/lambda/">lambda</a></li><li><a href="https://www.finecloud.ch/tags/softwareentwicklung/">software development</a></li></ul><div class="post__share"></div></footer></article><div class="post__related related"><div class="wrapper"><h2 class="h5 related__title">You should also read:</h2><article class="related__item"><div class="feed__meta"><time datetime="2022-07-02T17:34" class="feed__date">Juli 2, 2022</time></div><h3 class="h1"><a href="https://www.finecloud.ch/kubernetes-auf-proxmox-mit-ansible-und-terraform-teil-2.html">Kubernetes auf Proxmox mit Ansible und Terraform (Teil 2)</a></h3></article><article class="related__item"><div class="feed__meta"><time datetime="2022-07-01T18:59" class="feed__date">Juli 1, 2022</time></div><h3 class="h1"><a href="https://www.finecloud.ch/kubernetes-auf-proxmox-mit-ansible-und-terraform.html">Kubernetes auf Proxmox mit Ansible und Terraform (Teil 1)</a></h3></article></div></div></main><footer class="footer"><div class="footer__copyright"><p>Powered by Publii</p></div><button onclick="backToTopFunction()" id="backToTop" class="footer__bttop" aria-label="Back to top" title="Back to top"><svg><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#toparrow"/></svg></button></footer></div><script>window.publiiThemeMenuConfig = {
mobileMenuMode: 'sidebar',
animationSpeed: 300,
submenuWidth: 'auto',
doubleClickTime: 500,
mobileMenuExpandableSubmenus: true,
relatedContainerForOverlayMenuSelector: '.top',
};</script><script defer="defer" src="https://www.finecloud.ch/assets/js/scripts.min.js?v=6ca8b60e6534a3888de1205e82df8528"></script><script>var images = document.querySelectorAll('img[loading]');
for (var i = 0; i < images.length; i++) {
if (images[i].complete) {
images[i].classList.add('is-loaded');
} else {
images[i].addEventListener('load', function () {
this.classList.add('is-loaded');
}, false);
}
}</script><script defer="defer" src="https://www.finecloud.ch/media/plugins/syntaxHighlighter/prism.js"></script></body></html>