Explication pour le premier exemple d'extrait de
Le problème vient en jeu lors de l'exécution d'un traitement parallèle.
//double the even values and put that into a list.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 1, 2, 3, 4, 5);
List<Integer> doubleOfEven = new ArrayList<>();
numbers.stream()
.filter(e -> e % 2 == 0)
.map(e -> e * 2)
.forEach(e -> doubleOfEven.add(e)); // <--- Unnecessary use of side-effects!
Cette inutilement utilise des effets secondaires , bien que pas tous les effets secondaires sont mauvais, s'ils sont utilisés correctement lors de l'utilisation de flux, on doit fournir un comportement qui est sûr pour exécuter simultanément sur différents morceaux de l'entrée. c'est à dire l'écriture de code qui n'a pas accès partagé mutable données pour faire son travail.
La ligne:
.forEach(e -> doubleOfEven.add(e)); // Unnecessary use of side-effects!
utilise inutilement les effets secondaires et lorsqu'il est exécuté en parallèle, la non-thread-safety de l' ArrayList
entraînerait des résultats incorrects.
Un temps, j'ai lu un blog par Henrik Eichenhardt répondre à pourquoi partagé mutable état est la racine de tous les maux.
C'est un court raisonnement pour expliquer pourquoi partagé la mutabilité est pas bonne; extrait du blog.
le non-déterminisme = traitement parallèle + mutable état
Cette équation signifie que à la fois le traitement parallèle et
mutable état de résultat combiné de non-déterministe, le comportement du programme.
Si vous venez de faire le traitement en parallèle et ont seulement état immuable
tout est beau et il est facile de raisonner sur les programmes. Sur le
d'autre part, si vous voulez faire un traitement en parallèle avec les données mutable vous
besoin de synchroniser l'accès aux variables qui mutable
rend essentiellement ces sections du programme mono-thread. Ce n'est pas vraiment nouveau, mais je n'ai pas vu ce concept exprime de façon élégante. Un non-déterministe programme est cassé.
Ce blog va dériver de l'intérieur les détails du pourquoi de programmes parallèles sans synchronisation appropriée sont brisés, que vous pouvez trouver dans le lien ajouté.
Explication le deuxième exemple de l'extrait de
List<Integer> doubleOfEven2 =
numbers.stream()
.filter(e -> e % 2 == 0)
.map(e -> e * 2)
.collect(toList()); // No side-effects!
Il utilise une collection de réduction de l' opération sur les éléments de ce flux en utilisant un Collector
.
Ce est beaucoup plus sûr, plus efficaceet plus propice à la parallélisation.