J'ai le code suivant et je voudrais l'implémenter en utilisant des fonctions lambda juste pour le plaisir. Peut-on le faire en utilisant les opérations d'agrégation de base?
List<Integer> result = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
if (10 % i == 0) {
result.add(i);
if (i != 5) {
result.add(10 / i);
}
}
}
Utilisation de lambda:
List<Integer> result = IntStream.rangeClosed(1, 10)
.boxed()
.filter(i -> 10 % i == 0)
// a map or forEach function here?
// .map(return 10 / i -> if i != 5)
.collect(Collectors.toList());
L'observation essentielle ici est que votre problème implique une transformation non isomorphe: un seul élément d'entrée peut correspondre à zéro, un ou deux éléments de sortie. Chaque fois que vous remarquez cela, vous devez immédiatement commencer à rechercher une solution qui implique flatMap
au lieu de map
car c'est la seule façon de réaliser une telle transformation générale. Dans votre cas particulier, vous pouvez d'abord appliquer filter
pour un mappage d'éléments un à zéro, puis flatMap
pour un mappage un à deux:
List<Integer> result =
IntStream.rangeClosed(1, 10)
.filter(i -> 10 % i == 0)
.flatMap(i -> i == 5 ? IntStream.of(i) : IntStream.of(i, 10 / i))
.boxed()
.collect(toList());
Vous pouvez déclarer un corps pour un lambda. Par exemple:
Runnable run = () -> System.out.println("Hey");
Pourrait être
Runnable run = () -> {
System.out.println("Hey");
};
Dans ce corps, vous pouvez créer des instructions imbriquées:
Runnable run = () -> {
int num = 5;
if(num == 5) {
System.out.println("Hey");
}
};
Utilisez flatMap
lorsque vous essayez d'ajouter des éléments dans le pipeline ou un mappage 1 à plusieurs. La carte est une cartographie un à un.
ArrayList<Integer> result = (ArrayList<Integer>) IntStream.rangeClosed(1, 10)
.boxed()
.filter(i -> 10 % i == 0)
.flatMap((Integer i) -> {return i!=5 ? Stream.of(i, (10/i)):Stream.of(i);})
.collect(Collectors.toList());
Il en résulte la même liste que
ArrayList<Integer> result2 = new ArrayList<Integer>();
for (int i = 1; i <= 10; i++) {
if (10 % i == 0) {
result2.add(i);
if (i != 5) {
result2.add(10 / i);
}
}
}
Dans le cas où vous vous demandez quel chemin est plus rapide, la méthode de boucle est ~ 3 fois plus rapide que l'utilisation de flux.
Benchmark Mode Cnt Score Error Units
testStreams.Bench.loops avgt 5 75.221 ± 0.576 ns/op
testStreams.Bench.streams avgt 5 257.713 ± 13.125 ns/op
Tu peux le faire:
List<Integer> result1 = IntStream
.rangeClosed(1, 10)
.boxed()
.filter(i -> 10 % i == 0)
.map(i -> (i != 5 ? Stream.of(i, 10 / i) : Stream.of(i)))
.flatMap(Function.identity())
.collect(Collectors.toList());
Essayez d'utiliser flatMap
:
List<Integer> result = IntStream.rangeClosed(1, 10)
.boxed()
.flatMap((i) -> {
List<Integer> results = new ArrayList<>();
if (10 % i == 0) {
results.add(i);
if (i != 5) {
results.add(10 / i);
}
}
return results.stream();
})
.collect(Collectors.toList());