Étant donné le code suivant:
List<String> strList = new ArrayList<>(Arrays.asList("Java","Python","Php"));
Stream<String> jFilter = strList.stream().filter(str -> str.startsWith("J"));
strList.add("JavaScript"); // element added after filter creation
strList.add("JQuery"); // element added after filter creation
System.out.println(Arrays.toString(jFilter.toArray()));
qui produit:
[Java, JavaScript, JQuery]
Pourquoi JavaScript
et JQuery
apparaissent-ils dans le résultat filtré alors qu'ils ont été ajoutés après la création du flux filtré?
Jusqu'à la déclaration
System.out.println(Arrays.toString(jFilter.toArray()));
fonctionne, le flux ne fait rien. Une opération de terminal (toArray
dans l'exemple) est requise pour que le flux soit traversé et que vos opérations intermédiaires (filter
dans ce cas) soient exécutées.
Dans ce cas, vous pouvez, par exemple, capturer la taille de la liste avant d'ajouter d'autres éléments:
int maxSize = strList.size();
Stream<String> jFilter = strStream.limit(maxSize)
.filter(str -> str.startsWith("J"));
où limit(maxSize)
ne permettra pas que plus que les éléments initiaux passent par le pipeline.
C'est parce que le flux n'a jamais été évalué. vous n'avez jamais appelé "Terminal operation" sur ce flux pour qu'il soit exécuté car lazy.
Regardez une modification de votre code et de la sortie. Le filtrage a effectivement lieu lorsque vous appelez l’opérateur du terminal.
public static void main(String []args){
List<String> strList = new ArrayList<>();
strList.add("Java");
strList.add("Python");
strList.add("Php");
Stream<String> strStream = strList.stream();
Stream<String> jFilter = strStream.filter(str -> {
System.out.println("Filtering" + str);
return str.startsWith("J");
});
System.out.println("After Stream creation");
strList.add("JavaScript"); // element added after filter creation
strList.add("JQuery"); // element added after filter creation
System.out.println(Arrays.toString(jFilter.toArray()));
}
Sortie:
After Stream creation
FilteringJava
FilteringPython
FilteringPhp
FilteringJavaScript
FilteringJQuery
[Java, JavaScript, JQuery]
Comme expliqué dans la documentation officielle à l'adresse https://docs.Oracle.com/javase/8/docs/api/Java/util/stream/package-summary.html , les flux ne disposent pas de stockage, de même que plus comme des itérateurs que des collections, et sont évalués paresseusement.
Donc, rien ne se passe vraiment en ce qui concerne le flux jusqu'à ce que vous appeliez l'opération de terminal toArray ()
Le commentaire de @Hadi J mais il devrait être répondu selon les règles.
Parce que
streams
sont paresseux et lorsque vous appelez opération de terminal, il est exécuté.
La méthode toArray
est l'opération de terminal et elle fonctionne sur tout le contenu de votre liste. Pour obtenir un résultat prévisible, n'enregistrez pas la variable stream
dans une variable temporaire, car cela entraînerait des résultats trompeurs. Un meilleur code est:
String[] arr = strList.stream().filter(str -> str.startsWith("J")).toArray();