On m'a posé cette question lors d'une interview et je ne suis pas convaincu d'avoir donné la meilleure réponse possible. J'ai mentionné que vous pouvez faire une recherche parallèle et que les valeurs nulles ont été gérées par des moyens dont je ne me souviens pas. Maintenant, je réalise que je pensais aux options. Qu'est-ce que j'oublie ici? Ils prétendent que c'est un code meilleur ou plus concis, mais je ne suis pas sûr d'être d'accord.
Compte tenu de la brièveté de la réponse, il semble que ce n'était pas une question trop large après tout.
S'ils posent cette question lors des entretiens, et c'est clair qu'ils le sont, à quoi la décomposition pourrait-elle servir autre que de compliquer la recherche d'une réponse? Je veux dire, qu'est-ce que tu cherches? Je pourrais décomposer la question et avoir toutes les sous-questions répondues, mais ensuite créer une question parentale avec des liens vers toutes les sous-questions ... cela semble assez idiot. Pendant que nous y sommes, donnez-moi un exemple de question moins large. Je ne connais aucun moyen de ne poser qu'une partie de cette question et d'obtenir toujours une réponse significative. Je pourrais poser exactement la même question d'une manière différente. Par exemple, je pourrais demander "À quoi servent les flux?" ou "Quand est-ce que j'utiliserais un flux au lieu d'une boucle for?" ou "Pourquoi s'embêter avec des flux plutôt qu'avec des boucles for?" Ce sont tous exactement la même question.
... ou est-il considéré comme trop large parce que quelqu'un a donné une réponse très longue en plusieurs points? Franchement, n'importe qui au courant pourrait le faire avec pratiquement n'importe quelle question. Si vous êtes l'un des auteurs de la JVM, par exemple, vous pourriez probablement parler de boucles for toute la journée alors que la plupart d'entre nous ne le pourraient pas.
"Veuillez modifier la question pour la limiter à un problème spécifique avec suffisamment de détails pour identifier une réponse adéquate. Évitez de poser plusieurs questions distinctes à la fois. Consultez la page Comment poser pour obtenir de l'aide pour clarifier cette question."
Comme indiqué ci-dessous, une réponse adéquate a été donnée qui prouve qu'il y en a une et qu'elle est assez facile à fournir.
la source
Réponses:
Il est intéressant que la question de l'entrevue porte sur les avantages, sans poser de questions sur les inconvénients, car il y a les deux.
Les flux sont un style plus déclaratif . Ou un style plus expressif . Il peut être préférable de déclarer votre intention dans le code plutôt que de décrire comment cela se fait:
... dit clairement que vous filtrez les éléments correspondants d'une liste, alors que:
Dit "je fais une boucle". Le but de la boucle est enfoui plus profondément dans la logique.
Les flux sont souvent lacunaires . Le même exemple le montre. Terser n'est pas toujours meilleur, mais si vous pouvez être concis et expressif en même temps, tant mieux.
Les flux ont une forte affinité avec les fonctions . Java 8 introduit des lambdas et des interfaces fonctionnelles, ce qui ouvre toute une boîte à jouets de techniques puissantes. Les flux offrent le moyen le plus pratique et le plus naturel d'appliquer des fonctions à des séquences d'objets.
Les flux encouragent moins de mutabilité . C'est en quelque sorte lié à l'aspect de la programmation fonctionnelle - le type de programmes que vous écrivez à l'aide de flux ont tendance à être le type de programmes où vous ne modifiez pas les objets.
Les flux encouragent un couplage plus lâche . Votre code de gestion de flux n'a pas besoin de connaître la source du flux ou sa méthode de terminaison éventuelle.
Les flux peuvent exprimer succinctement un comportement assez sophistiqué . Par exemple:
Peut sembler à première vue comme s'il filtre tout le flux, puis renvoie le premier élément. Mais en fait, il
findFirst()
dirige toute l'opération, de sorte qu'il s'arrête efficacement après avoir trouvé un élément.Les flux offrent des possibilités de gains d'efficacité futurs . Certaines personnes ont évalué et constaté que les flux à un seul thread à partir de
List
s ou de tableaux en mémoire peuvent être plus lents que la boucle équivalente. Ceci est plausible car il y a plus d'objets et de frais généraux en jeu.Mais les flux évoluent. Outre la prise en charge intégrée de Java pour les opérations de flux parallèles, il existe quelques bibliothèques pour la réduction de carte distribuée utilisant Streams comme API, car le modèle s'adapte.
Désavantages?
Performances : une
for
boucle à travers un tableau est extrêmement légère en termes d'utilisation du tas et du processeur. Si la vitesse brute et l'économie de la mémoire sont une priorité, l'utilisation d'un flux est pire.Familiarité Le monde regorge de programmeurs procéduraux expérimentés, issus de nombreux langages, pour qui les boucles sont familières et les flux sont nouveaux. Dans certains environnements, vous souhaitez écrire du code familier à ce type de personne.
Frais généraux cognitifs . En raison de sa nature déclarative et de l'abstraction accrue de ce qui se passe en dessous, vous devrez peut-être créer un nouveau modèle mental de la relation entre le code et l'exécution. En fait, vous n'avez besoin de le faire que lorsque les choses tournent mal, ou si vous avez besoin d'analyser en profondeur les performances ou des bugs subtils. Quand ça "fonctionne juste", ça marche juste.
Les débogueurs s'améliorent, mais même maintenant, lorsque vous parcourez le code de flux dans un débogueur, cela peut être plus difficile que la boucle équivalente, car une boucle simple est très proche des variables et des emplacements de code avec lesquels un débogueur traditionnel fonctionne.
la source
Mis à part le plaisir syntaxique, les Streams sont conçus pour fonctionner avec des ensembles de données potentiellement infiniment volumineux, tandis que les tableaux, les collections et presque toutes les classes Java SE qui implémentent Iterable sont entièrement en mémoire.
Un inconvénient d'un Stream est que les filtres, les mappages, etc., ne peuvent pas lever d'exceptions vérifiées. Cela fait d'un Stream un mauvais choix pour, par exemple, les opérations d'E / S intermédiaires.
la source
Stream<Row>
- ou il serait possible d'écrire sa propreStream
implémentation en enveloppant les opérations de curseur de résultat DB.Arrays.asList("test", null).stream().forEach(s -> System.out.println(s.length()));
Vous avez mal compris: les opérations parallèles utilisent
Stream
s, pasOptional
s.Vous pouvez définir des méthodes fonctionnant avec des flux: les prendre comme paramètres, les renvoyer, etc. Vous ne pouvez pas définir une méthode qui prend une boucle comme paramètre. Cela permet une opération de flux compliquée une fois et de l'utiliser plusieurs fois. Notez que Java a ici un inconvénient: vos méthodes doivent être appelées plutôt que
someMethod(stream)
celles de streamstream.someMethod()
, donc les mélanger complique la lecture: essayez de voir l'ordre des opérations dansDe nombreux autres langages (C #, Kotlin, Scala, etc.) autorisent une certaine forme de «méthodes d'extension».
Même lorsque vous n'avez besoin que d'opérations séquentielles et que vous ne voulez pas les réutiliser, afin de pouvoir utiliser des flux ou des boucles, des opérations simples sur les flux peuvent correspondre à des changements assez complexes dans les boucles.
la source
Optional
est une alternative ànull
, mais cela n'a rien à voir avec les opérations parallèles. À moins que "maintenant je réalise que je pensais aux options" dans votre question ne parle que de lanull
manipulation?Vous bouclez sur une séquence (tableau, collection, entrée, ...) parce que vous voulez appliquer une fonction aux éléments de la séquence.
Les flux vous permettent de composer des fonctions sur des éléments de séquence et permettent d' implémenter les fonctions les plus courantes (ex: mappage, filtrage, recherche, tri, collecte, ...) indépendamment d'un cas concret.
Par conséquent, étant donné une tâche de bouclage dans la plupart des cas, vous pouvez l'exprimer avec moins de code en utilisant Streams, c'est-à-dire que vous gagnez en lisibilité .
la source
Je dirais sa parallélisation qui est si facile à utiliser. Essayez d'itérer sur des millions d'entrées en parallèle avec une boucle for. Nous allons vers de nombreux processeurs, pas plus vite; donc plus il est facile de courir en parallèle, mieux c'est, et avec
Stream
s c'est un jeu d'enfant.Ce que j'aime beaucoup, c'est la verbosité qu'ils offrent. Il faut peu de temps pour comprendre ce qu'ils font et produisent réellement par opposition à la façon dont ils le font.
la source