web-dev-qa-db-fra.com

Comment créer un flux infini avec Java 8

Existe-t-il un moyen simple de créer un flux infini à l’aide de Java-8 sans bibliothèques externes?

Par exemple en Scala: 

Iterator.iterate(0)(_ + 2)
65
sndyuk

Oui, il existe un chemin facile :

IntStream.iterate(0, i -> i + 2);

Avec comme cas d'utilisation:

IntStream.iterate(0, i -> i + 2)
         .limit(100)
         .forEach(System.out::println);

Qui imprime 0 à 198 en augmentant par pas de 2.

La méthode générique est:

Stream.iterate(T seed, UnaryOperator<T> f);

Ce dernier peut être plus rare dans l'utilisation.

93
skiwi

Voici un exemple:

PrimitiveIterator.OfInt it = new PrimitiveIterator.OfInt() {
    private int value = 0;

    @Override
    public int nextInt() {
        return value++;
    }

    @Override
    public boolean hasNext() {
        return true;
    }
};

Spliterator.OfInt spliterator = Spliterators.spliteratorUnknownSize(it,
    Spliterator.DISTINCT | Spliterator.IMMUTABLE |
    Spliterator.ORDERED | Spliterator.SORTED);

IntStream stream = StreamSupport.intStream(spliterator, false);

C'est un peu verbeux, comme vous le voyez. Pour imprimer les 10 premiers éléments de ce flux:

stream.limit(10).forEach(System.out::println);

Vous pouvez bien sûr aussi transformer les éléments, comme vous le faites dans votre exemple Scala:

IntStream plusTwoStream = stream.map(n -> n + 2);

Notez qu'il existe des flux infinis intégrés tels que Java.util.Random.ints() qui vous donne un flux infini d'entiers aléatoires.

7
Jesper

Il existe une autre solution possible dans Java 8:

AtomicInteger adder = new AtomicInteger();
IntStream stream = IntStream.generate(() -> adder.getAndAdd(2));

Important: un ordre de nombres n'est conservé que si le flux est séquentiel.


Il faut également noter qu'une nouvelle version du IntStream.iterate a été ajoutée depuis Java 9:

static IntStream iterate​(int seed,
                         IntPredicate hasNext,
                         IntUnaryOperator next);
  • seed - l'élément initial;
  • hasNext - un prédicat à appliquer aux éléments pour déterminer quand le flux doit se terminer;
  • next - une fonction à appliquer à l'élément précédent pour produire un nouvel élément.

Exemples:

IntStream stream = IntStream.iterate(0, i -> i >= 0, i -> i + 2);

IntStream.iterate(0, i -> i < 10, i -> i + 2).forEach(System.out::println);
1
Oleksandr

Vous pouvez construire votre propre InfiniteStream en implémentant stream et consumer et en composer les deux. Vous aurez peut-être besoin d'une file d'attente pour mettre vos données en file d'attente:

public class InfiniteStream<T> implements Consumer<T>, Stream<T> {
private final Stream<T> stream;
private final Queueing q;
...
public InfiniteStream(int length) {
    this.q = new Queueing(this.length);
    this.stream = Stream.generate(q);
    ...
}
    //implement stream methods
    //implement accept
}

vérifier le code complet ici https://Gist.github.com/bassemZohdy/e5fdd56de44cea3cd8ff

0
Bassem Reda Zohdy