web-dev-qa-db-fra.com

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

Je souhaite traiter des listes dans un objet XML Java. 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 d’utiliser le flux tant que je n’utilise pas le parallélisme? list.stream().filter().forEach()

122
membersound

Vous posez la mauvaise question. Vous posez des questions sur sequential par rapport à parallel alors que vous souhaitez traiter des éléments dans l'ordre , vous devez donc poser des questions sur . commande . Si vous avez un flux ordonné et effectuez des opérations qui garantissent le maintien de l’ordre, peu importe si le flux est traité en parallèle ou en séquence; la mise en œuvre maintiendra la commande.

La propriété ordonnée est distincte de parallèle vs séquentielle. Par exemple. Si vous appelez stream() sur un HashSet, le flux ne sera pas ordonné lors de l'appel de stream() sur un List renvoie un flux ordonné. Notez que vous pouvez appeler unordered() pour libérer le contrat de commande et potentiellement améliorer les performances. Une fois que le flux n’a plus d’ordre, il n’ya plus moyen de rétablir l’ordre. (La seule façon de transformer un flux non ordonné en un ordre est d'appeler sorted. Cependant, l'ordre résultant n'est pas nécessairement l'ordre d'origine).

Voir aussi la section "Commande" de la documentation du package Java.util.stream .

Afin de garantir la maintenance de la commande tout au long d’une opération de flux, vous devez étudier la documentation de la source du flux, de toutes les opérations intermédiaires et de l’opération de terminal pour déterminer si la commande est maintenue ou non (ou si la source a une commande dans la première endroit).

Cela peut être très subtil, par exemple Stream.iterate(T,UnaryOperator) crée un flux ordonné tandis que Stream.generate(Supplier) crée un non ordonné flux. Notez que vous avez également commis une erreur commune dans votre question, car forEach ne conserve pas la commande . Vous devez utiliser forEachOrdered si vous souhaitez traiter les éléments du flux dans un ordre garanti.

Ainsi, si votre list dans votre question est bien un _Java.util.List_, sa méthode stream() renverra un flux ordonné et filter ne modifiera pas l'ordre. Donc, si vous appelez list.stream().filter() .forEachOrdered(), tous les éléments seront traités séquentiellement dans l’ordre, alors que pour list.parallelStream().filter().forEachOrdered() les éléments pourraient ê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 du parallèle). exécution).

Si vous utilisez par exemple une opération comme

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

toute l'opération peut tirer parti de l'exécution en parallèle, mais la liste résultante sera toujours dans le bon ordre, que vous utilisiez un flux parallèle ou séquentiel.

296
Holger