Salut,
Envoyé par
L'aigle de Carthage
1- Est ce qu'on utlise le reduce avec 2 paramètres dans le cas de manipulation de String, et 3 paramètres dans le cas d'entiers?
Pas forcément.
En fait les deux premières versions de reduce() fonctionnent uniquement avec le type T de ton Stream : reduce(BinaryOperator<T>) et reduce(T identity, BinaryOperator<T> accumulator).
C'est à dire que le type de retour est du même type que le type des éléments de ton Stream.
La troisième version de reduce() est paramétré par un second type U, qui permet d'avoir un résultat de type différent de celui du Stream : reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
Envoyé par
L'aigle de Carthage
Est ce que somme ne représente pas le résultat déjà calculé ici?
pk l'utilisation de s1 et s2?
On est typiquement dans le cas précité : le type du Stream est différent de celui de ton résultat, et donc il faut utiliser la troisième version de reduce().
Ton code est tout à fait correct :
Integer ageTotal = persons.stream().reduce(0, (somme,p)->somme+=p.getAge(),(s1,s2)->s1+s2);
Et le troisième paramètre est primordiale lorsque le flux exécute en parallèle.
=> Le premier paramètre (identity) représenter la valeur initiale (0) dans ton cas.
=> Le second paramètre (accumulator) permet d'accumuler les objets de ton flux dans le résultat (cad rajouter l'age de la personne).
=> Le troisième paramètre (combiner) permet de gérer l’exécution en parallèle, et permet de combiner deux résultats.
En effet si le flux s’exécute en parallèle, il va être découpé en plusieurs petits bouts qui seront calculé en parallèles.
Le "combiner" permet donc de récupérer chacun des résultats et et les recombiner pour obtenir le résultat final.
A noter quand même que pour une somme tu aurais pu utiliser mapToInt() sur ton attribut pour obtenir un IntStream comportant des méthodes plus adaptées :
int age = persons.stream().mapToInt(Person::getAge).sum();
Enfin, la méthode reduce() n'est pas très adapté pour la concaténation de String.
Et ton code n'est pas très bon pour deux raisons car il génère une nouvelle String à chaque concaténation, ce qui peut s'avérer catastrophique sur de grande quantité de données :
String names = employees.stream().map(e->e.getName()).reduce("", (a,b)->a+" - "+b);
Il sera plus approprié d'utiliser un "collector", qui fonctionne sur le même principe mais dont le résultat est prévu pour s'accumuler dans un objet modifiable.
En gros çà donnerait ceci :
1 2 3 4 5
| String names = employees.stream()
.collect(StringBuilder::new,
(sb,e) -> sb.append(" - ").append(e.getName()),
(sb1, sb2) -> sb1.append(sb2)
).toString(); |
A noter qu'il y a le même "bug" que dans ton code initial : le résultat commence par ton séparateur " - ", et il faudrait gérer ce cas.
Mais en fait il existe déjà des "collectors" pour concaténer des chaines (ainsi que pour d'autres cas courant).
=> Voir la classe Collectors !
Ce qui donne tout simplement :
1 2 3
| String names = employees.stream()
.map(e->e.getName())
.collect(Collectors.joining(" - ")); |
a++
Partager