Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Leer Principes | Fundamenten en Functionele Mogelijkheden van Stream API
Stream-API

bookPrincipes

De principes van het werken met de Stream API zijn gebaseerd op de belangrijkste concepten van functioneel programmeren en luie evaluatie. Hieronder volgt een overzicht van de belangrijkste principes van de Stream API.

Luie evaluatie

Een van de kernprincipes van de Stream API is luie evaluatie.

Dit houdt in dat intermediaire operaties zoals filter() of map() niet direct worden uitgevoerd. Ze vormen slechts een keten van acties die pas worden uitgevoerd wanneer een terminale operatie, zoals collect() of forEach(), wordt aangeroepen.

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); long count = names.stream() .filter(name -> name.startsWith("A")) // Forming the operation .count(); // Triggering execution System.out.println(count); // Output: 1 } }

Deze code maakt een stream van een lijst met strings, filtert de elementen om alleen die te behouden die beginnen met de letter A, en telt hoeveel aan deze voorwaarde voldoen. Het resultaat (1) wordt afgedrukt omdat alleen Alice aan de voorwaarde voldoet.

Functionele programmeerstijl

De Stream API maakt gebruik van lambda-expressies en functionele interfaces voor gegevensverwerking. In plaats van de imperatieve aanpak met lussen, beschrijf je wat er met de gegevens moet gebeuren:

Main.java

Main.java

copy
1234567891011121314
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> fruits = List.of("apple", "banana", "cherry", "apricot", "blueberry"); List<String> result = fruits.stream() .map(String::toUpperCase) // Convert all strings to uppercase .skip(3) .toList(); // Collect the result into a new list System.out.println(result); } }

Deze code maakt een stream van een lijst met fruitsoorten, zet de strings om naar hoofdletters met behulp van map(), en slaat de eerste drie elementen over met skip(). Het resultaat wordt verzameld in een nieuwe lijst en afgedrukt, beginnend vanaf het vierde element.

Onveranderlijkheid van gegevens

De Stream API wijzigt de oorspronkelijke gegevens niet. Alle bewerkingen creëren een nieuwe stream of geven een resultaat terug zonder de collectie of array te wijzigen. Dit verhoogt de gegevensveiligheid en voorkomt onverwachte neveneffecten.

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); List<String> updateNames = names.stream() .filter(name -> name.startsWith("A")) .toList(); System.out.println(names); // Output: [Alice, Bob, Charlie] } }

De Stream API filtert de lijst namen om een nieuwe stream, updateNames, te creëren die alleen elementen bevat die beginnen met de letter A. De oorspronkelijke lijst namen blijft echter ongewijzigd, omdat de Stream API de gegevens niet direct wijzigt, wat gegevensveiligheid waarborgt en neveneffecten voorkomt.

Streams zijn slechts één keer te gebruiken

Een stream kan slechts één keer worden gebruikt. Nadat een terminale bewerking is uitgevoerd, is de stream niet langer beschikbaar voor verdere verwerking.

Main.java

Main.java

copy
123456789101112
package com.example; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { Stream<String> stream = List.of("Alice", "Bob").stream(); stream.forEach(System.out::println); stream.forEach(System.out::println); // Error: Stream has already been used } }

Hier wordt een stream gemaakt van een lijst met strings en wordt elk element naar de console geprint. Nadat de stream voor de eerste keer is gebruikt, kan deze niet opnieuw worden gebruikt, wat een fout veroorzaakt als u probeert opnieuw forEach() aan te roepen.

Parallelle verwerking

De Stream API ondersteunt parallelle streams, waardoor snellere gegevensverwerking op multi-core systemen mogelijk is. Dit wordt uitgebreider besproken hier

Main.java

Main.java

copy
1234567891011
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = List.of(1, 2, 3, 4, 5); numbers.parallelStream() .forEach(System.out::println); // Elements are processed in parallel } }

Deze code maakt een parallelle stream van een lijst met getallen en print elk element naar de console. Door gebruik te maken van parallelStream() wordt parallelle verwerking van de lijstelementen mogelijk, wat de uitvoering kan versnellen bij het werken met grote datasets.

Codezuiverheid en Leesbaarheid

Het gebruik van de Stream API maakt de code meer declaratief. In plaats van te beschrijven hoe een taak moet worden uitgevoerd (zoals met lussen), wordt beschreven wat precies moet gebeuren. Dit verhoogt de leesbaarheid en vereenvoudigt het onderhoud van de code.

Voorbeeld met een lus:

List<String> names = List.of("Alice", "Bob", "Charlie");
for (String name : names) {
    System.out.println(name);
}

Voorbeeld met Stream API:

List<String> names = List.of("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);

In het eerste lusvoorbeeld beschrijven we expliciet hoe we door de lijst moeten itereren en de elementen moeten afdrukken, terwijl we in het tweede voorbeeld met de Stream API eenvoudig aangeven wat er moet gebeuren: itereren door de elementen en deze afdrukken. Dit maakt de code meer declaratief en leesbaar.

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 1. Hoofdstuk 2

Vraag AI

expand

Vraag AI

ChatGPT

Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.

Awesome!

Completion rate improved to 2.33

bookPrincipes

Veeg om het menu te tonen

De principes van het werken met de Stream API zijn gebaseerd op de belangrijkste concepten van functioneel programmeren en luie evaluatie. Hieronder volgt een overzicht van de belangrijkste principes van de Stream API.

Luie evaluatie

Een van de kernprincipes van de Stream API is luie evaluatie.

Dit houdt in dat intermediaire operaties zoals filter() of map() niet direct worden uitgevoerd. Ze vormen slechts een keten van acties die pas worden uitgevoerd wanneer een terminale operatie, zoals collect() of forEach(), wordt aangeroepen.

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); long count = names.stream() .filter(name -> name.startsWith("A")) // Forming the operation .count(); // Triggering execution System.out.println(count); // Output: 1 } }

Deze code maakt een stream van een lijst met strings, filtert de elementen om alleen die te behouden die beginnen met de letter A, en telt hoeveel aan deze voorwaarde voldoen. Het resultaat (1) wordt afgedrukt omdat alleen Alice aan de voorwaarde voldoet.

Functionele programmeerstijl

De Stream API maakt gebruik van lambda-expressies en functionele interfaces voor gegevensverwerking. In plaats van de imperatieve aanpak met lussen, beschrijf je wat er met de gegevens moet gebeuren:

Main.java

Main.java

copy
1234567891011121314
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> fruits = List.of("apple", "banana", "cherry", "apricot", "blueberry"); List<String> result = fruits.stream() .map(String::toUpperCase) // Convert all strings to uppercase .skip(3) .toList(); // Collect the result into a new list System.out.println(result); } }

Deze code maakt een stream van een lijst met fruitsoorten, zet de strings om naar hoofdletters met behulp van map(), en slaat de eerste drie elementen over met skip(). Het resultaat wordt verzameld in een nieuwe lijst en afgedrukt, beginnend vanaf het vierde element.

Onveranderlijkheid van gegevens

De Stream API wijzigt de oorspronkelijke gegevens niet. Alle bewerkingen creëren een nieuwe stream of geven een resultaat terug zonder de collectie of array te wijzigen. Dit verhoogt de gegevensveiligheid en voorkomt onverwachte neveneffecten.

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); List<String> updateNames = names.stream() .filter(name -> name.startsWith("A")) .toList(); System.out.println(names); // Output: [Alice, Bob, Charlie] } }

De Stream API filtert de lijst namen om een nieuwe stream, updateNames, te creëren die alleen elementen bevat die beginnen met de letter A. De oorspronkelijke lijst namen blijft echter ongewijzigd, omdat de Stream API de gegevens niet direct wijzigt, wat gegevensveiligheid waarborgt en neveneffecten voorkomt.

Streams zijn slechts één keer te gebruiken

Een stream kan slechts één keer worden gebruikt. Nadat een terminale bewerking is uitgevoerd, is de stream niet langer beschikbaar voor verdere verwerking.

Main.java

Main.java

copy
123456789101112
package com.example; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { Stream<String> stream = List.of("Alice", "Bob").stream(); stream.forEach(System.out::println); stream.forEach(System.out::println); // Error: Stream has already been used } }

Hier wordt een stream gemaakt van een lijst met strings en wordt elk element naar de console geprint. Nadat de stream voor de eerste keer is gebruikt, kan deze niet opnieuw worden gebruikt, wat een fout veroorzaakt als u probeert opnieuw forEach() aan te roepen.

Parallelle verwerking

De Stream API ondersteunt parallelle streams, waardoor snellere gegevensverwerking op multi-core systemen mogelijk is. Dit wordt uitgebreider besproken hier

Main.java

Main.java

copy
1234567891011
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = List.of(1, 2, 3, 4, 5); numbers.parallelStream() .forEach(System.out::println); // Elements are processed in parallel } }

Deze code maakt een parallelle stream van een lijst met getallen en print elk element naar de console. Door gebruik te maken van parallelStream() wordt parallelle verwerking van de lijstelementen mogelijk, wat de uitvoering kan versnellen bij het werken met grote datasets.

Codezuiverheid en Leesbaarheid

Het gebruik van de Stream API maakt de code meer declaratief. In plaats van te beschrijven hoe een taak moet worden uitgevoerd (zoals met lussen), wordt beschreven wat precies moet gebeuren. Dit verhoogt de leesbaarheid en vereenvoudigt het onderhoud van de code.

Voorbeeld met een lus:

List<String> names = List.of("Alice", "Bob", "Charlie");
for (String name : names) {
    System.out.println(name);
}

Voorbeeld met Stream API:

List<String> names = List.of("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);

In het eerste lusvoorbeeld beschrijven we expliciet hoe we door de lijst moeten itereren en de elementen moeten afdrukken, terwijl we in het tweede voorbeeld met de Stream API eenvoudig aangeven wat er moet gebeuren: itereren door de elementen en deze afdrukken. Dit maakt de code meer declaratief en leesbaar.

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 1. Hoofdstuk 2
some-alt