2017-10-16 7 views
2

Je veux vraiment connaître la différence exacte entre Stream.reduce() and Stream.parallel.reduce()Stream.reduce() vs Stream.parallel.reduce()

Pour effacer tout ce que je créé un petit programme et a trouvé ce résultat ne correspond pas avec les mêmes valeurs.

public class Test { 

    public static void main(String[] args) { 
     int a = Stream.of(1, 2, 3).map(i -> i * 10).reduce(5, (abc, cde) -> abc + cde); 
     int b = Stream.of(1, 2, 3).map(i -> i * 10). 
     parallel().reduce(5, (abc, cde) -> abc + cde); 
     System.out.println(a == b) //False; 
    } 
} 

Alors, est-ce cela signifie que les deux sont différents si oui s'il vous plaît aidez-moi à comprendre comment ils sont différents dans la fonctionnalité sage?

+2

https://stackoverflow.com/a/32867283/2711488 – Holger

Répondre

5

Il semble que vous utilisiez abusivement la fonction reduce. Lorsque vous utilisez reduce avec une valeur d'identité, vous devez vous assurer que l'identité correspond à une identité sur la fonction de réduction associative.

Voir le documentation complet, et une bonne explication de ce que reduce fait here. Le reducejavadoc dit:

La valeur d'identité doit être une identité pour la fonction de l'accumulateur. Cela signifie que pour tous t, accumulator.apply(identity, t) est égal à t. La fonction accumulateur doit être une fonction associative.

Dans votre cas, 5 est pas l'identité de la fonction + que vous utilisez pour réduire, ce qui conduit à des résultats étranges lors de l'utilisation réduit parallèle. 0 est l'identité de l'addition, donc une façon correcte de calculer serait d'ajouter 5 à la liste, et d'utiliser reduce(0, (x,y)-> x+y)). En outre, puisque vous réduisez un flux de int à un int, vous pouvez utiliser simplement reduce((x,y)->x+y).

La raison est que la réduction parallèle utilise l'information que l'identité est une identité mathématique à optimiser pour l'exécution parallèle. Dans votre cas, il va injecter plusieurs valeurs identity dans le calcul.

+0

Merci pour l'information, donc cela signifie qu'ils ne sont pas les mêmes fonctions –

+4

Non, ce sont la même méthode. Lisez le dernier paragraphe de la réponse. ---- Le cas linéaire commence par 5, ajoute 10, ajoute 20, ajoute 30, se termine par ** 65 **. ---- Dans le cas parallèle, il peut diviser les nombres en [1, 2] et [3]. Alors maintenant, il commence par 5, ajoute 10, ajoute 20; et en parallèle commence par 5, ajoute 30. Maintenant, il résume les sous-résultats de 35 et 35, se termine par ** 70 **. ---- Lors de l'utilisation de réduire avec deux paramètres, le premier doit avoir aucun effet dans la fonction de réduction, en particulier lors de l'utilisation parallèle. Mais 5 ** a ** un effet en utilisant '+'. –

+3

En principe, il serait également légal pour un flux de retourner simplement la somme de tous les éléments quand vous dites 'reduce (5, (x, y) -> x + y)', sans jamais y ajouter '5'. Même pour un flux séquentiel. – Holger