---
title: 'Iterator vom Stream besorgen'
url: 'https://tutego.de/blog/javainsel/2018/03/iterator-vom-stream-besorgen'
markdown: 'https://tutego.de/blog/javainsel/2018/03/iterator-vom-stream-besorgen.md'
date: '2018-03-01'
description: 'Sich einen Iterator von einem Stream geben zu lassen ist nützlich, 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ässt sich in Stream mit einer…'
taxonomy:
  category:
    - Allgemein
    - Insel
    - 'Java 8'
---

# Iterator vom Stream besorgen

![Illustration einer tropischen Insel mit Palmen und einem hohen Berg](https://tutego.de/blog/javainsel/user/themes/tutego/images/insel-cover.jpg)# Java Blog für Programmierer

[Java Blog für Programmierer](https://tutego.de/blog/javainsel/)

## Iterator vom Stream besorgen

01.03.2018 · [Christian Ullenboom](https://tutego.de/blog/javainsel/author/admin/)

Sich einen `Iterator` von einem `Stream` geben zu lassen ist nützlich, 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ässt sich in `Stream` mit einer Generator-Funktion einfach aufbauen, in `Iterator` aber nicht.

Beispiel: Aus zwei Streams sollen jeweils alterrnierend das nächste Element konsumiert und ausgegeben werden.

```java
Iterator iterator1 = Stream.of( 1, 3, 5 ).iterator();

Iterator iterator2 = Stream.of( 2, 4, 6, 7, 8 ).iterator();

while ( iterator1.hasNext() || iterator2.hasNext() ) {

  if ( iterator1.hasNext() )

    System.out.println( iterator1.next() );

  if ( iterator2.hasNext() )

    System.out.println( iterator2.next() );

}
```

`Iterator` ist ein Datentyp, der häufig in der Rückgabe verwendet wird, seltener als Parametertyp. Mit `stream.iterator()` ist es aber möglich, die Daten vom `Stream` genau an solchen Stellen zu übergeben. Einen `Stream` in einen `Iterator` zu konvertieren, um diesen dann mit `hasNext()`/next() abzulaufen, ist wenig sinnvoll, hierfür bietet sich genauso gut `forEach(…)` auf dem `Stream` an.

#### `Stream` ist nicht `Iterable`

Der Typ `Stream` bietet eine Methode `iterator()`, erweitert jedoch die Schnittstelle `Iterable` nicht. In der Javadoc ist bei `iterator()` die Bemerkung „terminale Operation“ vermerkt, denn der `Iterator` saugt den `Stream` leer, sodass ein zweiter `iterator()`-Aufruf auf einem `Stream` nicht möglich ist. Bei Klassen, die `Iterable` implementieren, muss ein Aufruf von `iterator()` beliebig oft möglich sein. Bei Streams ist das nicht gegeben, da die Streams selbst nicht für die Daten stehen wie eine `Collection`, die daher `Iterable` ist.

#### `Iterator` in `Stream` umwandeln

Ist auf der anderen Seite ein `Iterator` gegeben, lässt sich dieser nicht direkt in einen `Stream` bringen. Iteratoren können wie Streams unendlich sein, und es gibt keinen Weg, die Daten eines Iterators als Quelle zu benutzen. Natürlich ist es möglich, den `Iterator` abzulaufen und daraus einen neuen `Stream` aufzubauen, dann muss der `Iterator` aber endlich sein.

Beispiel: Die Methode `ImageIO.getImageReadersBySuffix(String)` liefert einen `Iterator` von ImageReader-Objekten – sie sollen über einen Strom zugänglich sein:

```java
Builder builder = Stream.builder();
 for ( Iterator iter = ImageIO.getImageReadersBySuffix( "jpg" );
       iter.hasNext(); )
   builder.add( iter.next() );
 Stream stream = builder.build();
 System.out.println( stream.count() );    // 1
```

Einen anderen Weg geht StreamSupport.

Ist eine alte Enumeration gegeben, hilft `Collections.list(enumeration).stream()`, denn `list(…)` liefert eine `ArrayList` mit allen Einträgen; `list(Iterator)` gibt es da hingegen nicht.

### `iterator()` von BaseStream und PrimitiveIterator.OfXXX

Die Schnittstelle `Stream` deklariert keine abstrakte `iterator()`-Methode, sondern bekommt die Methode vom Obertyp BaseStream vererbt. BaseStream ist insgesamt Basistyp von:

- `Stream`<T>, `DoubleStream`, `IntStream`, `LongStream`

Alle diese drei Typen haben damit `iterator()`-Methdoden, doch die Rückgaben sind unterschiedlich:

Typiterator()-Methdoden und RückgabeStream<T>`Iterator`<T> `iterator()`DoubleStreamPrimitiveIterator.OfDouble `iterator()`IntStreamPrimitiveIterator.OfInt `iterator()`LongStreamPrimitiveIterator.OfInt `iterator()`

*Unterschiedliche Rückgaben der Iteratoren*

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:

- `default void forEachRemaining(Consumer<? super *WrapperTyp*> action)`
- `default void forEachRemaining(*WrapperTyp*Consumer action)`
- `default *WrapperTyp* next()`
- *PrimitiverTyp* next*PrimitiverTyp*()

Statt *WrapperTyp* und *PrimitiverTyp* ist dann Double, `Integer`, Long und double, int, double einzusetzen.

Beispiel: Ein vom `Stream` abgeleiter `Iterator` besorgt Zahlen. Diese werden in einem anderen `Stream` eingesetzt.

```java
PrimitiveIterator.OfInt counter =

  IntStream.iterate( 1, Math::incrementExact ).iterator();

Stream.of( "Telegram", "WhatsApp", "Facebook Messenger", "Insta" )

      .map( s -> counter.nextInt() + ". " + s )

      .forEach( System.out::println );
```

Kategorien: [Allgemein](https://tutego.de/blog/javainsel/category/allgemein/), [Insel](https://tutego.de/blog/javainsel/category/insel/), [Java 8](https://tutego.de/blog/javainsel/category/java-8/)

[← Alle Beiträge](https://tutego.de/blog/javainsel/)

---

## Navigation

- Next: [Spring Boot 2.0 freigegeben](https://tutego.de/blog/javainsel/2018/03/spring-boot-2-0-freigegeben.md)
