Ein Stream baut eine Pipeline aus faulen Zwischenoperationen, die nichts tut, bis eine Terminaloperation läuft, und dann fließen die Elemente in einem Durchgang durch, weshalb filter vor map einen Unterschied macht. Parallel Streams teilen die Quelle auf den gemeinsamen Common ForkJoinPool auf. Nimm sie nur für große, billig aufteilbare, CPU-lastige Arbeit ohne geteilten veränderlichen Zustand, und nie für blockierendes I/O, weil du damit einen Pool blockierst, den die ganze Anwendung teilt.
Warum Interviewer das fragen
Der Interviewer will wissen, ob du Faulheit, Zustandslosigkeit und die Stellen verstehst, an denen Parallel Streams schiefgehen, denn Fehlgebrauch ist häufig und schadet über den geteilten Pool auch fremdem Code. Sie hören außerdem auf seiteneffektfreie Lambdas und korrekten Collector-Einsatz. Das zeigt, ob du Streams schreibst, weil sie klarer sind, oder weil sie modern aussehen.
So baust du deine Antwort auf
- Erklär die Faulheit und den einen Durchgang bei der Terminaloperation.
- Nenn die Voraussetzungen für korrekte parallele Ausführung.
- Warn vor dem geteilten Common Pool und blockierenden Aufrufen.
- Sag, wie du entscheidest: messen, nicht annehmen.
Beispielantwort
Zwischenoperationen bauen nur eine Pipeline; es passiert nichts, bis eine Terminaloperation Elemente hindurchzieht, und jedes Element wird durch die gesamte Kette geschoben, statt die Collection einmal pro Operation zu durchlaufen. Deshalb spielt die Reihenfolge eine Rolle, frühes Filtern spart Arbeit, und deshalb können kurzschließende Operationen wie findFirst die ganze Quelle vorzeitig stoppen. Bei Parallel Streams bin ich vorsichtig. Sie teilen die Quelle auf und laufen auf dem Common ForkJoinPool, den sich die gesamte JVM teilt, ein langsamer Parallel Stream in einem Request kann also alles andere verzögern, das ihn benutzt. Damit fällt jede blockierende Arbeit raus: ich habe erlebt, wie ein Parallel Stream mit HTTP-Calls jeden anderen Parallel Stream im Prozess ausgehungert hat. Wo sie wirklich helfen, ist eine große In-Memory-Berechnung über ein Array oder eine ArrayList, die sich gleichmäßig aufteilen lassen, ohne geteilten veränderlichen Zustand und ohne Abhängigkeit von der Reihenfolge. Selbst dann benchmarke ich, weil der Overhead fürs Aufteilen und Zusammenführen den Gewinn bei Collections mit ein paar tausend Elementen oft auffrisst. Brauche ich einen eigenen Pool, lasse ich den Stream in meinem eigenen ForkJoinPool laufen statt im Common Pool.
Steht dieses Vorstellungsgespräch bald an? GhostPilot hört bei deinem Live-Call mit, erkennt die Frage in dem Moment, in dem sie gestellt wird, und bringt dir eine strukturierte Antwort in Echtzeit auf den Bildschirm. Probier es im nächsten Mock aus, oder hol dir einen $29 Session Pass, kein Abo, für den Ernstfall.
So funktioniert esNachfragen, mit denen du rechnen solltest
- Warum sind LinkedList und Streams aus einem Iterator schlechte Kandidaten für Parallelität?
- Was ist der Unterschied zwischen reduce und collect?
- Wie zerlegen zustandsbehaftete Lambdas einen Parallel Stream?
Weitere Fragen für Java-Entwickler
Dein Interviewer stellt seine eigene Version davon. Kopier deine echte Stellenbeschreibung in den kostenlosen Question Predictor und bekomm die 20 Fragen, die diese Rolle am wahrscheinlichsten stellt, samt dem, worauf jede wirklich abzielt.
Meine Fragen vorhersagen