<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://mletkin.net/index.php?action=history&amp;feed=atom&amp;title=Streams%3A_Java_8_Streams_Einf%C3%BChrung</id>
	<title>Streams: Java 8 Streams Einführung - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://mletkin.net/index.php?action=history&amp;feed=atom&amp;title=Streams%3A_Java_8_Streams_Einf%C3%BChrung"/>
	<link rel="alternate" type="text/html" href="https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;action=history"/>
	<updated>2026-05-06T20:04:50Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in MimiPedia</subtitle>
	<generator>MediaWiki 1.39.4</generator>
	<entry>
		<id>https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=157&amp;oldid=prev</id>
		<title>Ullrich: /* Mach&#039; was mit: Verarbeitung der Objekte */</title>
		<link rel="alternate" type="text/html" href="https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=157&amp;oldid=prev"/>
		<updated>2023-09-24T17:26:42Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Mach&amp;#039; was mit: Verarbeitung der Objekte&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 24. September 2023, 17:26 Uhr&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l237&quot;&gt;Zeile 237:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Zeile 237:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;für Parallelisierung gewappnet; falls das eines Tages gewünscht sein sollte.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;für Parallelisierung gewappnet; falls das eines Tages gewünscht sein sollte.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== Mach&amp;#039; was &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;mit&lt;/del&gt;: Verarbeitung der Objekte ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== Mach&amp;#039; was &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;damit&lt;/ins&gt;: Verarbeitung der Objekte ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#039;&amp;#039;Ein&amp;#039;&amp;#039; Use Case für Streams ist die Verarbeitung einer Menge von Objekten. Hierfür dient die Methode {{java|foreach()}}. Als&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#039;&amp;#039;Ein&amp;#039;&amp;#039; Use Case für Streams ist die Verarbeitung einer Menge von Objekten. Hierfür dient die Methode {{java|foreach()}}. Als&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Parameter dient ein λ-Ausdruck das das Interface {{java|Consumer{{java| implementiert. Es nimmt ein Objekt des Eingabe-Stroms&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Parameter dient ein λ-Ausdruck das das Interface {{java|Consumer{{java| implementiert. Es nimmt ein Objekt des Eingabe-Stroms&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Ullrich</name></author>
	</entry>
	<entry>
		<id>https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=116&amp;oldid=prev</id>
		<title>Ullrich: Ullrich verschob die Seite Java 8 Streams Einführung nach Streams: Java 8 Streams Einführung</title>
		<link rel="alternate" type="text/html" href="https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=116&amp;oldid=prev"/>
		<updated>2023-03-09T17:39:17Z</updated>

		<summary type="html">&lt;p&gt;Ullrich verschob die Seite &lt;a href=&quot;/index.php?title=Java_8_Streams_Einf%C3%BChrung&quot; class=&quot;mw-redirect&quot; title=&quot;Java 8 Streams Einführung&quot;&gt;Java 8 Streams Einführung&lt;/a&gt; nach &lt;a href=&quot;/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&quot; title=&quot;Streams: Java 8 Streams Einführung&quot;&gt;Streams: Java 8 Streams Einführung&lt;/a&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 9. März 2023, 17:39 Uhr&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;de&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(kein Unterschied)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Ullrich</name></author>
	</entry>
	<entry>
		<id>https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=39&amp;oldid=prev</id>
		<title>Ullrich: Ullrich verschob die Seite In Java 8 Streams Einführung nach Java 8 Streams Einführung, ohne dabei eine Weiterleitung anzulegen</title>
		<link rel="alternate" type="text/html" href="https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=39&amp;oldid=prev"/>
		<updated>2021-04-21T20:36:19Z</updated>

		<summary type="html">&lt;p&gt;Ullrich verschob die Seite &lt;a href=&quot;/index.php?title=In_Java_8_Streams_Einf%C3%BChrung&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;In Java 8 Streams Einführung (Seite nicht vorhanden)&quot;&gt;In Java 8 Streams Einführung&lt;/a&gt; nach &lt;a href=&quot;/index.php?title=Java_8_Streams_Einf%C3%BChrung&quot; class=&quot;mw-redirect&quot; title=&quot;Java 8 Streams Einführung&quot;&gt;Java 8 Streams Einführung&lt;/a&gt;, ohne dabei eine Weiterleitung anzulegen&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 21. April 2021, 20:36 Uhr&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;de&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(kein Unterschied)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Ullrich</name></author>
	</entry>
	<entry>
		<id>https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=38&amp;oldid=prev</id>
		<title>Ullrich: Ullrich verschob die Seite Einführung in Java 8 Streams nach In Java 8 Streams Einführung, ohne dabei eine Weiterleitung anzulegen</title>
		<link rel="alternate" type="text/html" href="https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=38&amp;oldid=prev"/>
		<updated>2021-04-21T20:36:00Z</updated>

		<summary type="html">&lt;p&gt;Ullrich verschob die Seite &lt;a href=&quot;/index.php?title=Einf%C3%BChrung_in_Java_8_Streams&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Einführung in Java 8 Streams (Seite nicht vorhanden)&quot;&gt;Einführung in Java 8 Streams&lt;/a&gt; nach &lt;a href=&quot;/index.php?title=In_Java_8_Streams_Einf%C3%BChrung&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;In Java 8 Streams Einführung (Seite nicht vorhanden)&quot;&gt;In Java 8 Streams Einführung&lt;/a&gt;, ohne dabei eine Weiterleitung anzulegen&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 21. April 2021, 20:36 Uhr&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;de&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(kein Unterschied)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Ullrich</name></author>
	</entry>
	<entry>
		<id>https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=28&amp;oldid=prev</id>
		<title>Ullrich: Ullrich verschob die Seite Editing Einführung in Java 8 Streams nach Einführung in Java 8 Streams, ohne dabei eine Weiterleitung anzulegen</title>
		<link rel="alternate" type="text/html" href="https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=28&amp;oldid=prev"/>
		<updated>2021-04-10T15:19:10Z</updated>

		<summary type="html">&lt;p&gt;Ullrich verschob die Seite &lt;a href=&quot;/index.php?title=Editing_Einf%C3%BChrung_in_Java_8_Streams&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Editing Einführung in Java 8 Streams (Seite nicht vorhanden)&quot;&gt;Editing Einführung in Java 8 Streams&lt;/a&gt; nach &lt;a href=&quot;/index.php?title=Einf%C3%BChrung_in_Java_8_Streams&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Einführung in Java 8 Streams (Seite nicht vorhanden)&quot;&gt;Einführung in Java 8 Streams&lt;/a&gt;, ohne dabei eine Weiterleitung anzulegen&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 10. April 2021, 15:19 Uhr&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;de&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(kein Unterschied)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Ullrich</name></author>
	</entry>
	<entry>
		<id>https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=14&amp;oldid=prev</id>
		<title>Ullrich am 29. Juli 2020 um 19:15 Uhr</title>
		<link rel="alternate" type="text/html" href="https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=14&amp;oldid=prev"/>
		<updated>2020-07-29T19:15:22Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 29. Juli 2020, 19:15 Uhr&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l5&quot;&gt;Zeile 5:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Zeile 5:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;elegantem, übersichtlichem Code; darauf liegt das Augenmerk dieses Beitrags. Er ist als Einführung zu betrachten&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;elegantem, übersichtlichem Code; darauf liegt das Augenmerk dieses Beitrags. Er ist als Einführung zu betrachten&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;und kann daher nicht alle Aspekte beleuchten. Es wird vielmehr versucht das abstrakte Konzept zu beschreiben,&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;und kann daher nicht alle Aspekte beleuchten. Es wird vielmehr versucht das abstrakte Konzept zu beschreiben,&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;nicht wie die Verarbeitung durch die JDK-Implementierung geschieht&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;.&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;nicht wie die Verarbeitung durch die JDK-Implementierung geschieht.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Der Begriff &amp;quot;Stream&amp;quot; wird unglücklicherweise für zwei verschiedene Dinge verwendet. Zum einen ist damit der&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Der Begriff &amp;quot;Stream&amp;quot; wird unglücklicherweise für zwei verschiedene Dinge verwendet. Zum einen ist damit der&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Ullrich</name></author>
	</entry>
	<entry>
		<id>https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=5&amp;oldid=prev</id>
		<title>Ullrich: Die Seite wurde neu angelegt: „Category:Java Man kann Java-8-Streams als ein Konzept beschreiben, mit dem eine Menge von Objekten in gleichartiger Weise verarbeitet werden kann. Die Vera…“</title>
		<link rel="alternate" type="text/html" href="https://mletkin.net/index.php?title=Streams:_Java_8_Streams_Einf%C3%BChrung&amp;diff=5&amp;oldid=prev"/>
		<updated>2020-07-29T17:08:52Z</updated>

		<summary type="html">&lt;p&gt;Die Seite wurde neu angelegt: „&lt;a href=&quot;/index.php?title=Kategorie:Java&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Kategorie:Java (Seite nicht vorhanden)&quot;&gt;Category:Java&lt;/a&gt; Man kann Java-8-Streams als ein Konzept beschreiben, mit dem eine Menge von Objekten in gleichartiger Weise verarbeitet werden kann. Die Vera…“&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Category:Java]]&lt;br /&gt;
Man kann Java-8-Streams als ein Konzept beschreiben, mit dem eine Menge von Objekten in gleichartiger Weise&lt;br /&gt;
verarbeitet werden kann. Die Verarbeitung muß nicht unbedingt sequentiell erfolgen, Tatsächlich wurden Streams&lt;br /&gt;
als Konzept für die parallele Verarbeitung eingeführt. Die Verarbeitung von Listen mit Java-Steams führt zu&lt;br /&gt;
elegantem, übersichtlichem Code; darauf liegt das Augenmerk dieses Beitrags. Er ist als Einführung zu betrachten&lt;br /&gt;
und kann daher nicht alle Aspekte beleuchten. Es wird vielmehr versucht das abstrakte Konzept zu beschreiben,&lt;br /&gt;
nicht wie die Verarbeitung durch die JDK-Implementierung geschieht..&lt;br /&gt;
&lt;br /&gt;
Der Begriff &amp;quot;Stream&amp;quot; wird unglücklicherweise für zwei verschiedene Dinge verwendet. Zum einen ist damit der&lt;br /&gt;
Strom der Objekte gemeint, die verarbeitet werden sollen. Das ist mehr eine bildliche Vorstellung dessen, was im&lt;br /&gt;
Innern der Stream-Implementierung passiert, denn so etwas wie eine &amp;quot;Röhre&amp;quot;, durch die die Objekte im&lt;br /&gt;
Wortessinne hindurchschwimmen existiert im Java-Programm natürlich nicht. Zum anderen ist damit ein Java-&lt;br /&gt;
Objekt gemeint, das das Stream-Interface implementiert. Das ist tatsächlich etwas, das man im Java-Code&lt;br /&gt;
wiederfindet, anfassen und verwenden kann. Im Folgenden wird der Begriff &amp;quot;Stream&amp;quot; für das verarbeitende Java-&lt;br /&gt;
Objekt verwendet und der Begriff &amp;quot;Strom&amp;quot; für den Objekt-Strom. &amp;quot;Stream&amp;quot; kann auch als Bezeichnung für das&lt;br /&gt;
Stream-Konzept als Ganzes stehen.&lt;br /&gt;
&lt;br /&gt;
Man kann sich das Stream-Objekt wie ein Rohrleitungssystem vorstellen, in das ein Strom von Objekten&lt;br /&gt;
hineingeschüttet wird. Beim Durchlaufen wird der Strom gefiltert, eingekocht und mit Zusätzen angereichert. Das&lt;br /&gt;
Leitungsende verschließt ein Stöpsel mit einem Hahn, der nur die Tropfen durchläßt, die das vollständige&lt;br /&gt;
Rohrsystem passiert haben und das Ergebnis bilden. Die Art der Flüssigkeit kann sich beim Durchlaufen des&lt;br /&gt;
Leitungssystems ändern – aber lassen wir uns durch das Bild nicht zu weit von den Streams fortspülen...&lt;br /&gt;
&lt;br /&gt;
== Wie die Verarbeitung abläuft ==&lt;br /&gt;
Die Verwendung eines {{java|Stream}}-Objekts besteht aus drei Schritten:&lt;br /&gt;
&lt;br /&gt;
Im ersten Schritt muß zunächst ein {{java|Stream}}-Objekt erzeugt werden, mit dem die Objekte verarbeitet werden&lt;br /&gt;
können. Diesem {{java|Stream}}-Objekt werden dann im zweiten Schritt Arbeitsanweisungen hinzugefügt die angeben, was&lt;br /&gt;
mit den Objekten geschehen soll, die später als &amp;quot;Strom&amp;quot; durch die gedachte Röhre fließen. Sie können Objekte&lt;br /&gt;
verändern, umwandeln, Objekte herausfiltern und vieles mehr. Der dritte Schritt schließt die Verarbeitung durch&lt;br /&gt;
eine Anweisung ab, die den Ergebnis-Strom &amp;quot;abfüllt&amp;quot;. Man kann den gesamten Strom auf Flaschen ziehen (also zum&lt;br /&gt;
Beispiel alle verarbeiteten Objekte in eine Liste füllen), ein einzelnes Objekt herauspicken oder den Strom auf eine&lt;br /&gt;
einzige Eigenschaft des Ergebnis-Stroms reduzieren (zum Beispiel auf die Anzahl der enthaltenen Objekte).&lt;br /&gt;
Abweichend von der Analogie muß man man sich bereits beim Erzeugen des {{java|Stream}}-Objekts entscheiden, welche&lt;br /&gt;
Objekte man durch die Rohrleitung schickt. Glücklicherweise ist die Erzeugung eines {{java|Stream}}-Objekts aber deutlich&lt;br /&gt;
einfacher als die Installation einer sanitären Anlage...&lt;br /&gt;
&lt;br /&gt;
Typischerweise schreibt man die komplette Verarbeitung via Method-Chaining in eine einzige Anweisung. Das&lt;br /&gt;
Zählen aller Zahlen einer Liste die größer als 100 sind, könnte zum Beispiel so aussehen (die Erklärung der&lt;br /&gt;
Methoden folgt später):&lt;br /&gt;
{{java|code=Stream.of(10, 4711, 815).filter(x -&amp;gt; x &amp;gt; 100).count();}}&lt;br /&gt;
Der Strom der Objekte beginnt tatsächlich erst zu fließen, wenn die abschließende Methode von Schritt drei&lt;br /&gt;
aufgerufen wird (im Beispiel ist das die Methode {{java|count()}}). Man muß die Methoden daher nicht unmittelbar&lt;br /&gt;
hintereinenader ausführen, sondern kann – wenn erforderlich – die Konstruktion des {{java|Stream}}-Objekts schrittweise&lt;br /&gt;
ausführen und dann durch Ausführen der Abschluß-Methode die Verarbeitung starten. In der Rohrleitungs-Analogie&lt;br /&gt;
wird das Leitungssystem installiert – der Installateur muß zwischendurch mal ein anderes Rohrsystem aufsuchen –&lt;br /&gt;
dann wird am Leitungs-Ende ein Hahn aufgeschraubt und erst wenn dieser geöffnet wird, beginnt die Flüssigkeit zu fließen.&lt;br /&gt;
&lt;br /&gt;
Der Stream ist also ein Mechanismus zur Verarbeitung und nicht zur Speicherung. Diese Erkenntnis ist essentiell! Der Stream&lt;br /&gt;
verhält sich damit ähnlich wie das Optional. Tatsächlich handelt es sich um einen Einweg-Mechanismus, der nach&lt;br /&gt;
Abschluß des Streams verbraucht ist und nicht wieder verwendet werden kann – für jede Verarbeitung muß daher ein&lt;br /&gt;
neues {{java|Stream}}-Objekt erzeugt werden. Spätestens hier endet die Rohrleitungs-Analogie...&lt;br /&gt;
&lt;br /&gt;
Der Stream muß die Objekte bei der Verarbeitung nicht notwendigerweise verändern, auch &amp;quot;rein untersuchende&amp;quot; Operationen, wie das Suchen von&lt;br /&gt;
Objekten mit bestimmten Eigenschaften läßt sich mit Streams sehr übersichtlich und effizient durchführen.&lt;br /&gt;
Aber genug der Theorie, schauen wir uns die drei Schritte zum Aufbau eines Streams an ein paar – mehr oder&lt;br /&gt;
minder – praktischen Beispiel an. Wir betrachten die drei genannten Schritte und lernen verschiedene Methoden&lt;br /&gt;
kennen, die zu diesem Schritt gehören.&lt;br /&gt;
&lt;br /&gt;
== Schritt 1: Streams erzeugen ==&lt;br /&gt;
Betrachten wir zunächst die Erzeugung des Streams. Der typische Anwendungsfall beginnt mit einer Sammlung von&lt;br /&gt;
Objekten die irgendwo im Speicher herumliegen und verarbeitet werden möchten. Java bietet einige Möglichkeiten&lt;br /&gt;
an um einen Stream zu erzeugen, der aus einem Haufen von Objekten einen Strom formt.&lt;br /&gt;
&lt;br /&gt;
Im einfachsten Fall hat man eine Liste von Literalen. Hier bietet sich die statische Methode {{java|Stream.of}} &lt;br /&gt;
aus dem {{java|Stream}}-Interfaces an:&lt;br /&gt;
{{java|code=Stream&amp;lt;String&amp;gt; stream = Stream.of(&amp;quot;This&amp;quot;, &amp;quot;is&amp;quot;, &amp;quot;a&amp;quot;, &amp;quot;test&amp;quot;);}}&lt;br /&gt;
Man kann die gleiche (überladene) Methode auch für klassische Java-Arrays verwenden:&lt;br /&gt;
{{java|code=&lt;br /&gt;
String[] liste = {&amp;quot;This&amp;quot;, &amp;quot;is&amp;quot;, &amp;quot;a&amp;quot;, &amp;quot;test&amp;quot;};&lt;br /&gt;
Stream&amp;lt;String&amp;gt; stream = Stream.of(liste);&lt;br /&gt;
}}&lt;br /&gt;
{{java|Stream}} ist ein generisches Interface. Jeder Stream liefert Objekte genau eines Typs. Die Streams in unseren&lt;br /&gt;
Beispielen liefern – der Einfachheit halber – Strings, aber selbstverständlich ist jeder Objekt-Typ erlaubt.&lt;br /&gt;
&lt;br /&gt;
Ungleich häufiger ist der Wunsch, einen Stream aus einem Java-Collection-Objekt zu erzeugen. Hier erzeugen wir&lt;br /&gt;
zur Demonstration erst ein {{java|List}}-Objekt aus einer Literal-Liste und erzeugen dann einen Stream aus der Liste:&lt;br /&gt;
{{java|code=List&amp;lt;String&amp;gt; liste = Arrays.asList(&amp;quot;This&amp;quot;, &amp;quot;is&amp;quot;, &amp;quot;a&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
Stream&amp;lt;String&amp;gt; stream = liste.stream();}}&lt;br /&gt;
In diesem Falle brauchen wir keine Hilfsfunktion, sondern erzeugen den Stream mit der Methode {{java|stream()}} direkt&lt;br /&gt;
aus dem {{java|List}}-Objekt. Ein Konzept, das man sehr gut auch für eigene Datenstrukturen verwenden kann um eine&lt;br /&gt;
Verarbeitung des Inhalts ohne Kenntnis der internen Struktur zu ermöglichen.&lt;br /&gt;
Nach dem gleichen Muster lassen sich auch aus Datei-Inhalten Streams erzeugen:&lt;br /&gt;
{{java|code=Stream&amp;lt;String&amp;gt; stream = Files.lines(Paths.get(fileName)));}}&lt;br /&gt;
Hier wird aus einer Text-Datei ein Stream von Strings erzeugt. Jeder String enthält den Text eine Zeile der Datei.&lt;br /&gt;
Weitere Möglichkeiten bieten Iteratoren und Generator-Funktionen, auf die hier nicht weiter eingegangen wird.&lt;br /&gt;
Auch die Möglichkeit, Streams zusammenzuführen oder aus einem Stream von {{java|List}}-Objekten einen Stream der&lt;br /&gt;
darin enthaltenen Objekte zu machen wird hier nicht näher erläutert. Es sei nur gesagt, daß da noch einiges zu&lt;br /&gt;
entdecken ist...&lt;br /&gt;
&lt;br /&gt;
== Schritt 2: Die Verarbeitung ==&lt;br /&gt;
Nachdem der Stream erzeugt ist, muß definiert werden, was mit dem Objekt-Strom passieren soll der später&lt;br /&gt;
hindurchrauscht. Das {{java|Stream}}-Interface bietet dazu eine Reihe von Methoden. Man kann sich diese Methoden&lt;br /&gt;
vorstellen als Ventile im Rohr. Vorne kommt ein Strom von Objekten hinein und hinten fließt ein Strom von&lt;br /&gt;
Objekten wieder hinaus. Der Typ der Objekte kann, muß dabei aber nicht verändert werden. Ändert sich dabei der&lt;br /&gt;
Typ der Objekte, ändert sich auch der Typ des {{java|Stream}}-Objekts. Eclipse ist dabei sehr hilfreich, den Überblick zu&lt;br /&gt;
behalten, mit welchem Typ man gerade arbeitet...&lt;br /&gt;
&lt;br /&gt;
Da wir mit Java-8 arbeiten, verwenden wir natürlich [[Lambdas in Java | λ-Ausdrücke]] um die zu verwendende Funktion zu&lt;br /&gt;
spezifizieren. Genau diese Möglichkeit macht die Streams zu einem extrem flexiblen und vielfältigen Mechanismus.&lt;br /&gt;
Die Auswahl an Stream-Methoden ist nicht erschöpfend und soll nur einen Eindruck geben von den verschiedenen&lt;br /&gt;
Möglichkeiten die die Verarbeitung hat.&lt;br /&gt;
&lt;br /&gt;
=== Objekte betrachten: filter() ===&lt;br /&gt;
Der vielleicht einfachste Use Case ist die Anwendung eines Filters. Seine Aufgabe ist es, Objekte des Stroms&lt;br /&gt;
durchzulassen oder herauszufiltern (und fallen zu lassen). Für die Angabe der Filterbedingung verwenden wir einen&lt;br /&gt;
λ-Ausdruck der das Interface {{java|Predicate}} implementiert. {{java|Predicate}} definiert eine Funktion, die ein Objekt vom Typ&lt;br /&gt;
des Eingabe-Stroms als Argument nimmt und als Ergebnis {{java|true}} oder {{java|false}} liefert. Nur Objekte, die die Bedingung&lt;br /&gt;
des Prädikats erfüllen werden durchgelassen. Als Beispiel bauen wir uns wieder ein {{java|List}}-Objekt, erzeugen einen&lt;br /&gt;
Stream und filtern alle {{java|null}}-Werte heraus:&lt;br /&gt;
{{java|code=List&amp;lt;String&amp;gt; liste = Arrays.asList(&amp;quot;This&amp;quot;, &amp;quot;is&amp;quot;, &amp;quot;a&amp;quot;, null, &amp;quot;test&amp;quot;);&lt;br /&gt;
Stream&amp;lt;String&amp;gt; stream = liste.stream().filter(x -&amp;gt; x != null);}}&lt;br /&gt;
Es entsteht dabei wieder ein Strom gleichen Typs (hier {{java|String}}), der gegebenenfalls weniger Objekte enthält als der&lt;br /&gt;
ursprüngliche Strom, aber garantiert keine neuen Objekte. Durch Hintereinanderschalten lassen sich Filter beliebig verketten:&lt;br /&gt;
{{java|code=Stream&amp;lt;String&amp;gt; stream = liste.stream().filter(x -&amp;gt; x != null).filter(x -&amp;gt; x.length() &amp;gt; 5);}}&lt;br /&gt;
Leider gibt es kein &amp;quot;negatives&amp;quot; Äquivalent zur {{java|filter}}-Methode, also eine Methode die diejenigen Objekte fallen&lt;br /&gt;
läßt, die das Prädikat erfüllen. Um das zu erreichen, muß man die {{java|filter}}-Methode mit einem ein entsprechenden,&lt;br /&gt;
negierten Prädikat verwenden.&lt;br /&gt;
&lt;br /&gt;
=== Objekte manipulieren: map() ===&lt;br /&gt;
Die mächtigste Funktion ist zweifellos {{java|map()}}. Sie erlaubt die Anwendung einer Funktion, die ein Objekt des&lt;br /&gt;
Eingangsstroms als Parameter nimmt und ein beliebiges Objekt als Ergebnis liefert. Damit kann man die Objekte&lt;br /&gt;
eines Streams verändern oder umwandeln. Ändert sich der Typ des Objekts durch die Anwendung der Funktion,&lt;br /&gt;
ändert sich damit auch der Typ des Ausgabe-Stroms. Nehmen wir wieder einen {{java|String}}-Stream, und &amp;quot;trimmen&amp;quot; die&lt;br /&gt;
Strings beim Durchlauf:&lt;br /&gt;
{{java|code=List&amp;lt;String&amp;gt; liste = Arrays.asList(&amp;quot;This &amp;quot;, &amp;quot; is &amp;quot;, &amp;quot; a &amp;quot;, null, &amp;quot; test&amp;quot;);&lt;br /&gt;
Stream&amp;lt;String&amp;gt; stream = liste.stream().map(String::trim);}}&lt;br /&gt;
Richtig, das wird schiefgehen und in einer Null-Pointer-Exception enden. Der Fehler wird aber noch nicht an &amp;#039;&amp;#039;dieser&amp;#039;&amp;#039; Stelle&lt;br /&gt;
auftreten, sondern erst, wenn der Stream im dritten Schritt abgeschlossen wird. Erst dann wird die&lt;br /&gt;
Verarbeitung gestartet, und die Objekte strömen los. Bevor wir {{java|trim()}} anwenden können, sollten wir also die {{java|null}}-&lt;br /&gt;
Werte herausfiltern. Dazu können wir die Methoden {{java|map()}} und {{java|filter()}} miteinander kombinieren.&lt;br /&gt;
Filtern wir also zuerst die {{java|null}}-Werte heraus; Java-8 bietet extra für diesen Fall eine convenience-Methode&lt;br /&gt;
in der {{java|Objects}}-Klasse:&lt;br /&gt;
{{java|code=List&amp;lt;String&amp;gt; liste = Arrays.asList(&amp;quot;This &amp;quot;, &amp;quot; is &amp;quot;, &amp;quot; a &amp;quot;, null, &amp;quot; test&amp;quot;);&lt;br /&gt;
Stream&amp;lt;String&amp;gt; stream = liste.stream().filter(Objects::nonNull).map(String::trim);}}&lt;br /&gt;
Bei der gezeigten Anwendung von {{java|map()}} bleibt der Typ des Streams unverändert, da {{java|String::trim}} ebenfalls Strings&lt;br /&gt;
liefert. Mit der String-Methode {{java|length()}} können wir zu jedem String dessen Länge bestimmen und so einen&lt;br /&gt;
{{java|integer}}-Stream erzeugen. Das Autoboxing von Java erzeugt dabei automatisch {{java|Integer}}-Objekte:&lt;br /&gt;
{{java|code=List&amp;lt;String&amp;gt; liste = Arrays.asList(&amp;quot;This &amp;quot;, &amp;quot; is &amp;quot;, &amp;quot; a &amp;quot;, null, &amp;quot; test&amp;quot;);&lt;br /&gt;
Stream&amp;lt;Integer&amp;gt; stream = liste.stream().filter(Objects::nonNull).map(String::length);}}&lt;br /&gt;
Es sei darauf hingewiesen, daß Java-8 eigene Implementierungen für Zahlen-Streams anbietet ({{java|IntStream}},&lt;br /&gt;
{{java|LongStream}} etc.) die wesentlich effizienter arbeiten. Das Beispiel sollte nur illustrieren, wie sich durch Anwendung&lt;br /&gt;
einer Funktion, die den Typ ändert, auch der Typ des Streams ändert. Die Klasse {{java|Integer}} im obigen Beispiel steht&lt;br /&gt;
stellvertretend für jede beliebige andere Klasse. Mit der Methode {{java|mapInt}} läßt sich zum Beispiel&lt;br /&gt;
ein {{java|IntStream}} erzeugen:&lt;br /&gt;
{{java|code=List&amp;lt;String&amp;gt; liste = Arrays.asList(&amp;quot;This &amp;quot;, &amp;quot; is &amp;quot;, &amp;quot; a &amp;quot;, null, &amp;quot; test&amp;quot;);&lt;br /&gt;
IntStream stream = liste.stream().filter(Objects::nonNull).mapToInt(String::length);}}&lt;br /&gt;
An dieser Stelle macht sich der Unterschied zwischen funktionaler und objektorientierter Sichtweise bemerkbar:&lt;br /&gt;
Der Methodenaufruf {{java|.filter(Objects::nonNull)}} liefert ein Objekt vom Typ {{java|Stream&amp;lt;String&amp;gt;}} das vom&lt;br /&gt;
Aufruf {{java|.map(String::length)}} in ein Objekt vom Typ {{java|Stream&amp;lt;Integer&amp;gt;}} umgewandelt wird. Technisch entsteht&lt;br /&gt;
dabei natürlich ein neues Objekt, aber es hilft dem Verständnis wenn man sich vorstellt, als gäbe es nur ein {{java|Stream}}-Objekt&lt;br /&gt;
das nach dem Aufruf von {{java|.filter(Objects::nonNull)}} einen {{java|String}}-Strom liefert und nach dem Aufruf&lt;br /&gt;
von {{java|.map(String::length)}} einen {{java|Integer}}-Strom. Oder übertragen auf die Rohrleitung: Das Leitungssystem (in&lt;br /&gt;
Analogie zum Stream-Objekt) liefert nach Aufstecken des ersten Ventils (dem non-null-filter) einen Strom von&lt;br /&gt;
Buchstabenketten und nach Aufstecken des zweiten Ventils (der length-map) einen Strom von Zahlen.&lt;br /&gt;
Der folgende JUnit-Schnipsel führt zu einer Exception im Assert:&lt;br /&gt;
{{java|code=List&amp;lt;String&amp;gt; liste = Arrays.asList(&amp;quot;This &amp;quot;, &amp;quot; is &amp;quot;, &amp;quot; a &amp;quot;, null, &amp;quot; test&amp;quot;);&lt;br /&gt;
Stream&amp;lt;String&amp;gt; stream = liste.stream();&lt;br /&gt;
Stream&amp;lt;String&amp;gt; streamNotNull = stream.map(String::trim);&lt;br /&gt;
Assert.assertEquals(5, stream.count());}}&lt;br /&gt;
&lt;br /&gt;
=== In alle Objekte des Strom hineinschauen: sorted() und distinct() ===&lt;br /&gt;
Wer Listen hat, hat auch bedarf nach Reihenfolge. Das {{java|Stream}}-Interface hat dafür zwei Methoden im Angebot.&lt;br /&gt;
Die Methode {{java|sorted()}} liefert einen Strom, der die Objekte im Eingangs-Strom nach der &amp;quot;natürlichen&amp;quot; Ordnung sortiert.&lt;br /&gt;
&lt;br /&gt;
Die Objekte des Eingangs-Stroms müssen dafür das Interface {{java|Comparable}} implementieren. Alternativ&lt;br /&gt;
kann man der Methode auch ein {{java|Comparator}}-Objekt übergeben, das Objekte des Eingabe-Typs vergleicht.&lt;br /&gt;
&lt;br /&gt;
Analog zum gleichnamigen SQL-statement vergleicht die Methode {{java|distinct()}} die Objekte des Eingangs-Stroms&lt;br /&gt;
mithilfe der Methode {{java|equals()}} und sorgt dafür, daß sich alle Objekte des Ausgangs-Stroms unterscheiden. Für&lt;br /&gt;
sortierte Ströme wird immer das erste Element durchgelassen, für unsortierte Ströme ist das nicht garantiert.&lt;br /&gt;
&lt;br /&gt;
=== Alle Objekte es Stroms betrachten: skip() und limit() ===&lt;br /&gt;
Ähnlich wie die {{java|filter}}-Methode dienen diese beiden Methoden dazu, Objekte aus dem Strom auszuschließen, im&lt;br /&gt;
Gegensatz zum Filter schauen diese Methoden jedoch nicht in die Objekte hinein.&lt;br /&gt;
&lt;br /&gt;
Die Methode {{java|skip()}} hat einen Parameter vom Typ long und überspringt Objekte im Strom.&lt;br /&gt;
&lt;br /&gt;
{{java|skip(5)}} hat zur Wirkung, daß die nächsten fünf Objekte des Eingabe-Stroms herausgefiltert werden und nicht&lt;br /&gt;
mehr im Ausgabe-Strom auftauchen.&lt;br /&gt;
&lt;br /&gt;
Die Methode {{java|limit()}} hat ebenfalls einen Parameter vom Typ long und beschränkt die Zahl der Objekte im&lt;br /&gt;
Ausgabe-Strom.&lt;br /&gt;
&lt;br /&gt;
{{java|limit(10)}} hat zur Wirkung, daß der Ausgabe-Strom maximal 10 Objekte enthält.&lt;br /&gt;
&lt;br /&gt;
=== Parallelisierung: parallel() und sequential() ===&lt;br /&gt;
Streams wurden eingeführt um die parallele Verarbeitung von Objekten zu ermöglichen. Mit der Methode&lt;br /&gt;
{{java|parallel()}} läßt sich aus jedem Strom eine Menge – potentiell parallel laufender – Ströme machen. Alle Objekte in&lt;br /&gt;
allen parallelen Strömen werden dann in der gleichen Art und Weise – so wie es der Stream definiert –&lt;br /&gt;
verarbeitet. Wenn die ausführende JVM eine Möglichkeit sieht, wird sie versuchen die Verarbeitung mit&lt;br /&gt;
verschiedenen Threads zu parallelisieren. Mit der Methode {{java|sequential()}} lassen sich die parallelen Ströme wieder&lt;br /&gt;
zusammenführen:&lt;br /&gt;
{{java|code=Stream&amp;lt;String&amp;gt; stream =&lt;br /&gt;
liste.stream().parallel().filter(Objects::nonNull).map(String::trim).sequential();}}&lt;br /&gt;
Welcher Strom dann welche Objekte zur Verarbeitung erhält ist nicht vorhersagbar. Die λ-Ausdrücke, die {{java|.map}}&lt;br /&gt;
verwendet, sollten daher immer zustandsfrei sein und keinen Bezug zu anderen Objekten haben. Und bevor man&lt;br /&gt;
ein Objekt verändert, sollte man überlegen, ob es nicht besser ist statt dessen ein neues Objekt zu erzeugen – so&lt;br /&gt;
wie {{java|String::trim}} es tatsächlich auch tut.&lt;br /&gt;
Streams entstammen der funktionalen Welt und funktionieren daher am besten mit seiteneffektfreien Funktionen&lt;br /&gt;
und mit unveränderlichen Objekten.&lt;br /&gt;
&lt;br /&gt;
== Schritt 3: Abschluß ==&lt;br /&gt;
Nachdem wir nun allerhand Schabernack mit den Objekten des Stroms getrieben haben, ist es an der Zeit den&lt;br /&gt;
Stream zu schließen und die Früchte unserer Arbeit zu ernten. Die meisten Abschluß-Funktionen des {{java|Stream}}-&lt;br /&gt;
Interface liefern ein einzelnes Ergebnis das in ein {{java|Optional}} verpackt ist. Das bietet uns die Möglichkeit mit leeren&lt;br /&gt;
Streams und ungültigen Ergebnissen umzugehen.&lt;br /&gt;
&lt;br /&gt;
Wie bereits erwähnt läuft der Stream mit Aufruf der Abschluß-Methode los und die (komplette) Verarbeitung wird durchgeführt.&lt;br /&gt;
&lt;br /&gt;
=== Quantoren: Alle oder Keins ===&lt;br /&gt;
Mit den Methoden {{java|anyMatch()}} und {{java|allMatch()}} kann geprüft werden, ob der Strom ein Objekt mit einer&lt;br /&gt;
bestimmten Eigenschaft enthält oder nicht. Sie arbeiten &amp;quot;lazy&amp;quot;, das heißt daß nur solange Objekte des Stroms&lt;br /&gt;
ausgewertet werden bis das Ergebnis feststeht. Auch das ist beim Design der verwendeten λ-Ausdrücke zu beachten.&lt;br /&gt;
Enthält ein λ-Ausdruck Seiteneffekte, muß man berücksichtigen daß diese nicht für jedes Objekt im Strom zur Geltung&lt;br /&gt;
kommen. Das folgende Beispiel prüft, ob die Liste (mindestens) einen String der Länge 5 enthält:&lt;br /&gt;
{{java|code=boolean fuenfExists = liste.stream().filter(Objects::nonNull).map(String::length).anyMatch(x -&amp;gt; x == 5);}}&lt;br /&gt;
Dieses Beispiel soll prüfen, ob alle Strings in der Liste ungleich {{java|null}} sind.&lt;br /&gt;
{{java|code=boolean alleGesetzt = liste.stream().allMatch(Objects::nonNull);}}&lt;br /&gt;
Statt &amp;quot;alle Objekte sind nicht null&amp;quot; kann man auch sagen &amp;quot;kein Objekt ist null&amp;quot;. Die passende dafür Methode ist&lt;br /&gt;
{{java|noneMatch()}}. Mit der Methode {{java|Objects::isNull}}, kann man also alternativ schreiben:&lt;br /&gt;
{{java|code=boolean alleGesetzt = liste.stream().noneMatch(Objects::isNull);}}&lt;br /&gt;
&lt;br /&gt;
=== Suchfunktionen: Wenn ja, welches? ===&lt;br /&gt;
Wenn das schiere Wissen um die Existenz nicht reicht, kann man sich auch das erste oder irgendein Objekt aus dem&lt;br /&gt;
Strom geben lassen. Die Methode {{java|findAny()}} liefert irgendein Objekt und {{java|findFirst()}} liefert das erste Objekt&lt;br /&gt;
das den Stream vollständig passiert hat. Hier suchen wir den ersten String, der nicht {{java|null}} ist:&lt;br /&gt;
{{java|code=Optional&amp;lt;String&amp;gt; firstOne = liste.stream().filter(Objects::nonNull).findFirst();}}&lt;br /&gt;
Da der Strom kein solches Objekt erhalten muß, ist das Ergebnis in ein {{java|Optional}} verpackt. Die Methode {{java|findAny()}}&lt;br /&gt;
tut im Prinzip das Gleiche, liefert aber nicht unbedingt das erste Objekt im Strom, das die gegebenen Eigenschaften&lt;br /&gt;
erfüllt. Der Unterschied der beiden Methoden wird erst bei parallelen Strömen spürbar, wenn die Reihenfolge der&lt;br /&gt;
Verarbeitung nicht mehr vorhersagbar ist.&lt;br /&gt;
&lt;br /&gt;
Für nicht-parallele Streams liefern beide Methoden das gleiche Ergebnis.&lt;br /&gt;
Man tut aber gut daran, für den jeweiligen Zweck die entsprechende Methode zu verwenden.&lt;br /&gt;
Erstens wird dadurch dei Intention des Programmierers dokumentiert und zweitens ist die Implementierung&lt;br /&gt;
für Parallelisierung gewappnet; falls das eines Tages gewünscht sein sollte.&lt;br /&gt;
&lt;br /&gt;
=== Mach&amp;#039; was mit: Verarbeitung der Objekte ===&lt;br /&gt;
&amp;#039;&amp;#039;Ein&amp;#039;&amp;#039; Use Case für Streams ist die Verarbeitung einer Menge von Objekten. Hierfür dient die Methode {{java|foreach()}}. Als&lt;br /&gt;
Parameter dient ein λ-Ausdruck das das Interface {{java|Consumer{{java| implementiert. Es nimmt ein Objekt des Eingabe-Stroms&lt;br /&gt;
und &amp;quot;liefert&amp;quot; {{java|void}} – also gar nichts. Das Objekt verschwindet zwar nicht, wird aber auch nicht weitergereicht, die&lt;br /&gt;
Verarbeitung endet hier.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel werden alle Strings die nicht {{java|null}} sind auf der System-Ausgabe ausgegeben:&lt;br /&gt;
{{java|code=liste.stream().filter(Objects::nonNull).forEach(System.out::print);}}&lt;br /&gt;
&lt;br /&gt;
=== Das Ergebnis sammeln: collect und count ===&lt;br /&gt;
Streams sind sehr gut dafür geeignet, um aus Listen neue Listen zu generieren. Dazu muß man den Ergebnis-Strom&lt;br /&gt;
auffangen und in ein passendes Gefäß füllen. Die Möglichkeiten, die Java hier bietet sind vielfältig und einen&lt;br /&gt;
eigenen Beitrag wert. Die einfachste Variante ist die Verwendung der Klasse {{java|Collectors}} um den Ergebnis-Strom in&lt;br /&gt;
ein {{java|Collection}}-Objekt zu füllen. Im Beispiel werden zunächst alle {{java|null}}-Werte aus dem Strom entfernt, das&lt;br /&gt;
Ergebnis sortiert und schließlich in ein neues {{java|List}}-Objekt gefüllt:&lt;br /&gt;
{{java|code=List&amp;lt;String&amp;gt; liste = Arrays.asList(&amp;quot;This&amp;quot;, &amp;quot;is&amp;quot;, &amp;quot;a&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
List&amp;lt;String&amp;gt; sort = liste.stream().filter(Objects::nonNull).sorted().collect(Collectors.toList());}}&lt;br /&gt;
Die Methode {{java|Collectors.toList()}} entscheidet dabei, welche {{java|List}}-Implementierung verwendet wird.&lt;br /&gt;
 &lt;br /&gt;
Eine weitere, einfache Anwendung ist das Zählen von Objekten. Hier zählen wir alle Objekte im Strom, die nicht {{java|null}} sind:&lt;br /&gt;
{{java|code=long anzahl = liste.stream().filter(Objects::nonNull).count();}}&lt;br /&gt;
Ein {{java|Optional}} brauchen wir diesmal nicht. Wenn der Ausgabe-Strom leer ist, ist das Ergebnis 0, also &amp;quot;zero&amp;quot; und nicht &amp;quot;null&amp;quot;.&lt;br /&gt;
Im Grunde genommen ist das ein Spezialfall eines Collectors, der die Liste auf ein einzelnes Objekt – in diesem Falle eine Zahl – reduziert.&lt;br /&gt;
&lt;br /&gt;
Es gibt weitere, komplexere Kollektoren, aber für den Anfang mögen diese einfachen Beispiele genügen.&lt;br /&gt;
Diese Kombination von Verarbeitung einer Liste und Zusammenführen der Ergebnisse ist auch als &amp;quot;map-reduce&amp;quot;-Pattern bekannt.&lt;br /&gt;
Weitergehende Betrachtungen zur collect-Methode finden sich hier: [[Streams: Ergebnis sammeln]].&lt;br /&gt;
&lt;br /&gt;
== Fazit ==&lt;br /&gt;
Der Beitrag konnte nur einen Einblick bieten, vor allem die Themen &amp;quot;Parallelisierung&amp;quot; und &amp;quot;Kollektoren&amp;quot; konnten nur&lt;br /&gt;
angerissen werden,&lt;br /&gt;
aber vielleicht wird hier schon deutlich, welches Potential in den Streams steckt. Java-9 erweitert das Konzept&lt;br /&gt;
zudem in Richtung &amp;quot;reactive&amp;quot;, was neue Möglichkeiten bietet – Streams gehört (wenigstens zu einem Teil) die Zukunft.&lt;br /&gt;
Zum Schluß noch der direkte Vergleich zwischen einer klassischen und einer Stream-Lösung.&lt;br /&gt;
Eine Methode soll uns dafür mitteilen, wieviele {{java|null}}-Werte eine String-Liste enthält.&lt;br /&gt;
&lt;br /&gt;
Mit einer &amp;quot;enhanced for&amp;quot;-Schleife sieht das so aus:&lt;br /&gt;
{{java|code=&lt;br /&gt;
private long count(List&amp;lt;String&amp;gt; liste) {&lt;br /&gt;
    int result = 0;&lt;br /&gt;
    for(String s : liste) {&lt;br /&gt;
        if (s != null) {&lt;br /&gt;
            result++;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
Mit Streams sieht das so aus:&lt;br /&gt;
{{java|code=&lt;br /&gt;
private long count(List&amp;lt;String&amp;gt; liste) {&lt;br /&gt;
    return liste.stream().filter(Objects::nonNull).count();&lt;br /&gt;
}&lt;br /&gt;
}}&lt;br /&gt;
Der Leser entscheide selbst, was schöner ist.&lt;/div&gt;</summary>
		<author><name>Ullrich</name></author>
	</entry>
</feed>