"Le flux a déjà été exploité ou fermé" Exception en Java

«Le flux a déjà été opéré ou fermé» Exception en Java

1. Vue d'ensemble

Dans ce bref article, nous allons discuter d'unException courant que nous pouvons rencontrer en travaillant avec la classeStream dans Java 8:

IllegalStateException: stream has already been operated upon or closed.

Nous découvrirons les scénarios dans lesquels cette exception se produit et les moyens possibles de l’éviter, ainsi que des exemples pratiques.

2. La cause

Dans Java 8, chaque classeStream représente une séquence de données à usage unique et prend en charge plusieurs opérations d'E / S.

UnStream ne doit être utilisé (en invoquant une opération de flux intermédiaire ou terminal) qu'une seule fois. Une implémentation Stream peut lancerIllegalStateException si elle détecte que leStream est réutilisé.

Chaque fois qu'une opération de terminal est appelée sur un objetStream, l'instance est consommée et fermée.

Par conséquent,we’re only allowed to perform a single operation that consumes a*Stream*, sinon, nous obtiendrons une exception qui indique que leStream a déjà été opéré ou fermé.

Voyons comment cela peut être traduit en un exemple pratique:

Stream stringStream = Stream.of("A", "B", "C", "D");
Optional result1 = stringStream.findAny();
System.out.println(result1.get());
Optional result2 = stringStream.findFirst();

Par conséquent:

A
Exception in thread "main" java.lang.IllegalStateException:
  stream has already been operated upon or closed

Après l'appel de la méthode#findAny(), lestringStream est fermé, par conséquent, toute autre opération sur leStream lèvera lesIllegalStateException, et c'est ce qui s'est passé après avoir appelé le#findFirst() méthode.

3. La solution

En termes simples, la solution consiste à créer un nouveauStream chaque fois que nous en avons besoin.

Nous pouvons, bien sûr, le faire manuellement, mais c'est là que l'interface fonctionnelle deSupplier devient vraiment pratique:

Supplier> streamSupplier
  = () -> Stream.of("A", "B", "C", "D");
Optional result1 = streamSupplier.get().findAny();
System.out.println(result1.get());
Optional result2 = streamSupplier.get().findFirst();
System.out.println(result2.get());

Par conséquent:

A
A

Nous avons défini l’objetstreamSupplier avec le typeStream<String>, qui est exactement le même type que celui renvoyé par la méthode#get(). LeSupplier est basé sur une expression lambda qui ne prend aucune entrée et renvoie un nouveauStream.

L'appel de la méthode fonctionnelleget() sur leSupplier renvoie un objetStream fraîchement créé, sur lequel nous pouvons effectuer en toute sécurité une autre opérationStream.

5. Conclusion

Dans ce rapide tutoriel, nous avons vu comment effectuer plusieurs fois des opérations de terminal sur unStream, tout en évitant les fameuxIllegalStateException qui sont lancés lorsque leStream est déjà fermé ou utilisé.

Vous pouvez trouver le code source complet et tous les extraits de code pour cet articleover on GitHub.