ProgrammatieJava ontwikkelaar

Leg uit wat de Java Stream API is, hoe deze correct te gebruiken voor collectieverwerkingsoperaties en welke nuances men moet overwegen bij het werken met gegevensstromen?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Geschiedenis van de vraag:

Stream API werd toegevoegd in Java 8 om functioneel programmeren en parallelle verwerking van collecties te vergemakkelijken. Het biedt een handige manier om ketens van bewerkingen op gegevens te beschrijven via lambda-expressies.

Probleem:

Zonder Stream API moest men omvangrijke imperatieve code schrijven voor filtering, sorteren en aggregeren van collecties. Er was potentieel voor fouten, moeilijkheden bij onderhoud en inefficiëntie bij het handmatig proberen toe te voegen van parallelisme.

Oplossing:

Stream API maakt het mogelijk om een pipeline op te bouwen van tussenliggende (intermediate) en terminale (terminal) bewerkingen. Stromen zijn lui, werken sequentieel of parallel met gegevens, en de code wordt compacter en expressiever.

Voorbeeld van collectieverwerking:

List<String> names = Arrays.asList("Anna", "Ivan", "Petr", "Eva"); names.stream() .filter(s -> s.length() > 3) .map(String::toUpperCase) .sorted() .forEach(System.out::println);

Belangrijke kenmerken:

  • Stromen zijn lui: berekeningen worden alleen uitgevoerd bij een terminale bewerking.
  • Na een terminale bewerking wordt de stroom als gesloten beschouwd.
  • Men kan overschakelen naar parallelle verwerking (parallelStream()), maar men moet rekening houden met de threadsafety van collecties en functies.

Vragen met een valstrik.

Kan men dezelfde Stream opnieuw gebruiken nadat deze is gesloten?

Nee, een poging om een gesloten Stream opnieuw te gebruiken gooit een IllegalStateException. Een stroom is eenmalig.

Heeft het wijzigen van de oorspronkelijke collectie na het maken van de Stream invloed?

Ja, als de collectie wordt gewijzigd na het maken van de Stream, maar vóór de terminale bewerking, kunnen er ConcurrentModificationException optreden.

Mag men externe wijzigbare variabelen gebruiken binnen Stream-bewerkingen?

Het wordt niet aanbevolen, omdat dit in een parallelle stroom kan leiden tot onverwachte fouten. Het is beter om mutabele bijeffecten in de Stream-pijplijn te vermijden.

Typische fouten en antipatterns

  • Het gebruik van mutabele externe variabelen binnen lambda/stream.
  • Het verwachten van een onmiddellijke effectiviteit van tussenliggende bewerkingen (er gebeurt niets zonder terminale bewerking).
  • Het toepassen van .parallelStream() op collecties die niet thread-safe zijn.

Voorbeeld uit het leven

Negatieve case

Een programmeur roept via Stream een bepaalde methode aan die een externe lijst wijzigt – dit werkt bij sequentiële uitvoering, maar leidt tot verstoring van de datastructuur bij parallelle uitvoering.

Voordelen:

  • De code is compact.

Nadelen:

  • Racecondities en uitzonderingen zijn mogelijk.
  • Schending van threadsafety.

Positieve case

De hele pijplijn wordt puur opgebouwd: bewerkingen hebben geen bijeffecten, er worden alleen onveranderlijke collecties gebruikt, en het uiteindelijke resultaat wordt verzameld via een collector.

Voordelen:

  • Veilige, leesbare, efficiënte code.
  • Eenvoudige overgang naar parallelle streams.

Nadelen:

  • Vereist gewenning aan de functionele stijl.