Un stream construit un pipeline d'opérations intermédiaires paresseuses qui ne fait rien tant qu'une opération terminale ne s'exécute pas, et les éléments traversent alors la chaîne en une seule passe, ce qui explique pourquoi filtrer avant de mapper compte. Les streams parallèles découpent la source sur le ForkJoinPool commun partagé. Ne les utilisez que pour du travail volumineux, facilement découpable, limité par le CPU, sans état mutable partagé, et jamais pour des entrées/sorties bloquantes, sinon vous immobilisez un pool que toute l'application partage.
Pourquoi les recruteurs posent cette question
Le recruteur veut savoir si vous comprenez la paresse, l'absence d'état et là où les streams parallèles dérapent, parce que le mésusage est courant et pénalise du code sans rapport via le pool partagé. Il écoute aussi si vos lambdas sont sans effet de bord et si vous utilisez correctement les collecteurs. Cela indique si vous écrivez des streams parce qu'ils sont plus clairs ou parce qu'ils font modernes.
Comment structurer votre réponse
- Expliquez la paresse et la passe unique au moment de l'opération terminale.
- Énoncez les conditions d'une exécution parallèle correcte.
- Avertissez sur le pool commun partagé et les appels bloquants.
- Dites comment vous décidez : mesurez, ne supposez pas.
Exemple de réponse
Les opérations intermédiaires ne font que construire un pipeline ; rien ne se passe tant qu'une opération terminale ne tire pas les éléments, et chaque élément est poussé à travers toute la chaîne plutôt que de parcourir la collection une fois par opération. C'est pour ça que l'ordre compte, que filtrer tôt fait moins de travail, et que des opérations en court-circuit comme findFirst peuvent arrêter la source très tôt. Pour les streams parallèles je suis prudent. Ils découpent la source et s'exécutent sur le ForkJoinPool commun, partagé par toute la JVM, donc un stream parallèle lent dans une requête peut ralentir tout le reste qui l'utilise. Cela exclut tout travail bloquant : j'ai vu un stream parallèle faisant des appels HTTP affamer tous les autres streams parallèles du processus. Là où ils aident vraiment, c'est un gros calcul en mémoire sur un tableau ou une ArrayList, qui se découpent uniformément, sans état mutable partagé et sans dépendance d'ordre. Même là je fais des benchmarks, parce que le surcoût de découpe et de fusion mange souvent le gain sur des collections de quelques milliers d'éléments. S'il me faut un pool dédié, j'exécute le stream dans mon propre ForkJoinPool plutôt que dans le commun.
Vous passez cet entretien bientôt ? GhostPilot écoute votre appel en direct, repère la question dès qu'elle est posée et affiche une réponse structurée à l'écran en temps réel. Essayez-le lors de votre prochain entretien blanc, ou prenez un Session Pass à $29, sans abonnement, pour le jour J.
Voir comment ça marcheQuestions de relance à prévoir
- Pourquoi LinkedList et les streams issus d'un iterator sont-ils de mauvais candidats au parallélisme ?
- Quelle est la différence entre reduce et collect ?
- Comment des lambdas avec état cassent-elles un stream parallèle ?
Autres questions pour Développeur Java
Votre recruteur posera sa propre version de celle-ci. Collez votre véritable fiche de poste dans le Question Predictor gratuit et obtenez les 20 questions que ce poste a le plus de chances de poser, avec ce que chacune cherche vraiment à sonder.
Prédire mes questions