{"id":4092,"date":"2018-03-01T14:31:18","date_gmt":"2018-03-01T12:31:18","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=4092"},"modified":"2018-03-01T14:31:18","modified_gmt":"2018-03-01T12:31:18","slug":"iterator-vom-stream-besorgen","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2018\/03\/iterator-vom-stream-besorgen\/","title":{"rendered":"Iterator vom Stream besorgen"},"content":{"rendered":"<p>Sich einen Iterator von einem Stream geben zu lassen ist n\u00fctzlich, weil dann der Zeitpunkt des Konsumierens vom Zeitpunkt des Stream-Aufbaus getrennt werden kann. Es ist nicht einfach mehrere Streams gleichzeitig abzulaufen, doch mit Iteratoren funktioniert das. Zudem l\u00e4sst sich in Stream mit einer Generator-Funktion einfach aufbauen, in Iterator aber nicht.<\/p>\n<p>Beispiel:\u00a0Aus zwei Streams sollen jeweils alterrnierend das n\u00e4chste Element konsumiert und ausgegeben werden.<\/p>\n<pre>Iterator&lt;Integer&gt; iterator1 = Stream.of( 1, 3, 5 ).iterator();\n\nIterator&lt;Integer&gt; iterator2 = Stream.of( 2, 4, 6, 7, 8 ).iterator();\n\n\n\n\nwhile ( iterator1.hasNext() || iterator2.hasNext() ) {\n\n\u00a0 if ( iterator1.hasNext() )\n\n\u00a0\u00a0\u00a0 System.out.println( iterator1.next() );\n\n\u00a0 if ( iterator2.hasNext() )\n\n\u00a0\u00a0\u00a0 System.out.println( iterator2.next() );\n\n}<\/pre>\n<p>Iterator ist ein Datentyp, der h\u00e4ufig in der R\u00fcckgabe verwendet wird, seltener als Parametertyp. Mit stream.iterator() ist es aber m\u00f6glich, die Daten vom Stream genau an solchen Stellen zu \u00fcbergeben. Einen Stream in einen Iterator zu konvertieren, um diesen dann mit hasNext()\/next() abzulaufen, ist wenig sinnvoll, hierf\u00fcr bietet sich genauso gut forEach(\u2026) auf dem Stream an.<\/p>\n<h4>Stream ist nicht Iterable<\/h4>\n<p>Der Typ Stream bietet eine Methode iterator(), erweitert jedoch die Schnittstelle Iterable nicht. In der Javadoc ist bei iterator() die Bemerkung \u201eterminale Operation\u201c vermerkt, denn der Iterator saugt den Stream leer, sodass ein zweiter iterator()-Aufruf auf einem Stream nicht m\u00f6glich ist. Bei Klassen, die Iterable implementieren, muss ein Aufruf von iterator() beliebig oft m\u00f6glich sein. Bei Streams ist das nicht gegeben, da die Streams selbst nicht f\u00fcr die Daten stehen wie eine Collection, die daher Iterable ist.<\/p>\n<h4>Iterator in Stream umwandeln<\/h4>\n<p>Ist auf der anderen Seite ein Iterator gegeben, l\u00e4sst sich dieser nicht direkt in einen Stream bringen. Iteratoren k\u00f6nnen wie Streams unendlich sein, und es gibt keinen Weg, die Daten eines Iterators als Quelle zu benutzen. Nat\u00fcrlich ist es m\u00f6glich, den Iterator abzulaufen und daraus einen neuen Stream aufzubauen, dann muss der Iterator aber endlich sein.<\/p>\n<p>Beispiel: Die Methode ImageIO.getImageReadersBySuffix(String) liefert einen Iterator von ImageReader-Objekten \u2013 sie sollen \u00fcber einen Strom zug\u00e4nglich sein:<\/p>\n<pre>Builder&lt;ImageReader&gt; builder = Stream.builder();\n for ( Iterator&lt;ImageReader&gt; iter = ImageIO.getImageReadersBySuffix( \"jpg\" );\n \u00a0\u00a0\u00a0\u00a0\u00a0 iter.hasNext(); )\n \u00a0 builder.add( iter.next() );\n Stream&lt;ImageReader&gt; stream = builder.build();\n System.out.println( stream.count() );\u00a0\u00a0\u00a0 \/\/ 1<\/pre>\n<p>Einen anderen Weg geht StreamSupport.<\/p>\n<p>Ist eine alte Enumeration gegeben, hilft Collections.list(enumeration).stream(), denn list(\u2026) liefert eine ArrayList mit allen Eintr\u00e4gen; list(Iterator) gibt es da hingegen nicht.<\/p>\n<h3>iterator() von BaseStream und PrimitiveIterator.OfXXX<\/h3>\n<p>Die Schnittstelle Stream deklariert keine abstrakte iterator()-Methode, sondern bekommt die Methode vom Obertyp BaseStream vererbt. BaseStream ist insgesamt Basistyp von:<\/p>\n<ul>\n<li>Stream&lt;T&gt;, DoubleStream, IntStream, LongStream<\/li>\n<\/ul>\n<p>Alle diese drei Typen haben damit iterator()-Methdoden, doch die R\u00fcckgaben sind unterschiedlich:<\/p>\n<table>\n<tbody>\n<tr>\n<td width=\"305\">Typ<\/td>\n<td width=\"588\">iterator()-Methdoden und R\u00fcckgabe<\/td>\n<\/tr>\n<tr>\n<td width=\"305\">Stream&lt;T&gt;<\/td>\n<td width=\"588\">Iterator&lt;T&gt; iterator()<\/td>\n<\/tr>\n<tr>\n<td width=\"305\">DoubleStream<\/td>\n<td width=\"588\">PrimitiveIterator.OfDouble iterator()<\/td>\n<\/tr>\n<tr>\n<td width=\"305\">IntStream<\/td>\n<td width=\"588\">PrimitiveIterator.OfInt iterator()<\/td>\n<\/tr>\n<tr>\n<td width=\"305\">LongStream<\/td>\n<td width=\"588\">PrimitiveIterator.OfInt iterator()<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><em>Unterschiedliche R\u00fcckgaben der Iteratoren<\/em><\/p>\n<p>PrimitiveIterator ist eine Schnittstelle aus dem Paket java.util mit eben drei inneren statischen Schnittstellen: OfDouble, OfInt und OfLong, die PrimitiveIterator erweiten. Jeder dieser drei inneren Typen hat eigene, aber symmetrische Methoden:<\/p>\n<ul>\n<li>default void forEachRemaining(Consumer&lt;? super <em>WrapperTyp<\/em>&gt; action)<\/li>\n<li>default void forEachRemaining(<em>WrapperTyp<\/em>Consumer action)<\/li>\n<li>default <em>WrapperTyp<\/em> next()<\/li>\n<li><em>PrimitiverTyp<\/em> next<em>PrimitiverTyp<\/em>()<\/li>\n<\/ul>\n<p>Statt <em>WrapperTyp<\/em> und <em>PrimitiverTyp<\/em> ist dann Double, Integer, Long und double, int, double einzusetzen.<\/p>\n<p>Beispiel:\u00a0Ein vom Stream abgeleiter Iterator besorgt Zahlen. Diese werden in einem anderen Stream eingesetzt.<\/p>\n<pre>PrimitiveIterator.OfInt counter =\n\n\u00a0 IntStream.iterate( 1, Math::incrementExact ).iterator();\n\nStream.of( \"Telegram\", \"WhatsApp\", \"Facebook Messenger\", \"Insta\" )\n\n\u00a0\u00a0\u00a0\u00a0\u00a0 .map( s -&gt; counter.nextInt() + \". \" + s )\n\n\u00a0\u00a0\u00a0\u00a0\u00a0 .forEach( System.out::println );<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Sich einen Iterator von einem Stream geben zu lassen ist n\u00fctzlich, weil dann der Zeitpunkt des Konsumierens vom Zeitpunkt des Stream-Aufbaus getrennt werden kann. Es ist nicht einfach mehrere Streams gleichzeitig abzulaufen, doch mit Iteratoren funktioniert das. Zudem l\u00e4sst sich in Stream mit einer Generator-Funktion einfach aufbauen, in Iterator aber nicht. Beispiel:\u00a0Aus zwei Streams sollen [&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":[1,11,66],"tags":[],"class_list":["post-4092","post","type-post","status-publish","format-standard","hentry","category-allgemein","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\/4092","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=4092"}],"version-history":[{"count":1,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/4092\/revisions"}],"predecessor-version":[{"id":4093,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/4092\/revisions\/4093"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=4092"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=4092"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=4092"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}