Comment assurer l'ordre de traitement dans les flux java8?


Je veux traiter des listes dans un objet java XML. Je dois assurer le traitement de tous les éléments dans l'ordre où je les ai reçus.

Dois-je donc appeler sequential sur chaque stream que j'utilise? list.stream().sequential().filter().forEach()

Ou est-ce suffisant pour simplement utiliser le flux tant que je n'utilise pas le parallélisme? list.stream().filter().forEach()

Author: Stuart Marks, 2015-03-23

2 answers

Vous posez la mauvaise question. Vous posez des questions sur sequential vs. parallelalors que vous voulez traiter les éléments dans l'ordre, vous devez donc poser des questions sur ordonnant. Si vous avez un flux ordonné et effectuez des opérations qui garantissent le maintien de l'ordre, peu importe que le flux soit traité en parallèle ou séquentiel; l'implémentation maintiendra l'ordre.

La propriété ordonnée est distincte de parallel vs sequential. E. g. si vous appelez stream() sur un HashSet le flux ne sera pas ordonné tandis que l'appel stream() sur un List renvoie un flux ordonné. Notez que vous pouvez appeler unordered() pour libérer le contrat de commande et potentiellement augmenter les performances. Une fois que le flux n'a pas de commande il n'y a aucun moyen de rétablir l'ordre. (La seule façon de transformer un flux non ordonné en un flux ordonné est d'appeler sorted, cependant, l'ordre résultant n'est pas nécessairement l'ordre d'origine).

Voir aussi le "Commande" article de la java.util.stream documentation du paquet .

Afin d'assurer la maintenance de la commande tout au long d'une opération de flux, vous devez étudier la documentation de la source du flux, toutes les opérations intermédiaires et l'opération du terminal pour savoir si elles maintiennent la commande ou non (ou si la source a une commande en premier lieu).

Cela peut être très subtile, par exemple Stream.iterate(T,UnaryOperator) crée un ordre flux tout en Stream.generate(Supplier) crée un flux non ordonné . Notez que vous avez également fait une erreur commune dans votre question forEach ne maintenir l'ordre. Vous devez utiliser forEachOrdered si vous voulez traiter le flux d'éléments dans un ordre garanti.

Donc, si votre list dans votre question est en effet un java.util.List, son stream() méthode retourne un ordonné flux et filter ne changera pas la commande. Donc, si vous appelez list.stream().filter() .forEachOrdered(), tous les éléments seront traités séquentiellement dans dans l'ordre, alors que pour list.parallelStream().filter().forEachOrdered() les éléments peuvent être traités en parallèle (par exemple par le filtre) mais l'action du terminal sera toujours appelée dans l'ordre (ce qui réduira évidemment l'avantage de l'exécution parallèle).

Si, par exemple, vous utilisez une opération comme

List<…> result=inputList.parallelStream().map(…).filter(…).collect(Collectors.toList());

Toute l'opération peut bénéficier d'une exécution parallèle, mais la liste résultante sera toujours dans le bon ordre, que vous utilisiez un flux parallèle ou séquentiel.

 234
Author: Holger, 2017-08-20 11:17:54

Liste.flux().séquentiel().filtrer().forEach ()

Traitera toujours la liste dans l'ordre car la liste elle-même est ordonnée.

Cependant, si nous utilisons

Liste.flux().parallèle()

Alors la commande n'est pas garantie pour le reste des opérations.

 2
Author: Jerin Joseph, 2016-12-05 12:51:46