Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Leer Praktijkvoorbeelden van het Gebruik van Stream API | Praktische Toepassingen van Stream API
Stream-API

bookPraktijkvoorbeelden van het Gebruik van Stream API

Code draait niet alleen om functionaliteit—het gaat ook om leesbaarheid. Goed gestructureerde code is eenvoudiger te onderhouden, aan te passen en uit te breiden.

Je bent een ontwikkelaar die de taak heeft om de code van iemand anders te reviewen en te verbeteren. In echte projecten wordt code vaak in haast geschreven, gekopieerd uit verschillende delen van het programma, of simpelweg niet ontworpen met leesbaarheid als uitgangspunt. Jouw taak is niet alleen om de code te begrijpen, maar ook om deze te verbeteren—door deze netter, bondiger en eenvoudiger onderhoudbaar te maken.

Op dit moment voer je een code review uit. Je zult een echt stuk code analyseren, de zwakke punten identificeren en het stap voor stap herstructureren met behulp van de Stream API.

Aan de slag

Stel je hebt een online winkel en je moet actieve gebruikers identificeren die ten minste drie bestellingen van $10.000 of meer hebben geplaatst. Dit helpt het marketingteam om de meest waardevolle klanten te herkennen en hen gepersonaliseerde aanbiedingen te doen.

Hier is de oorspronkelijke code vóór het herstructureren:

Main.java

Main.java

copy
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<User> users = List.of( new User("Alice", true, List.of(new Order(12000), new Order(15000), new Order(11000))), new User("Bob", true, List.of(new Order(8000), new Order(9000), new Order(12000))), new User("Charlie", false, List.of(new Order(15000), new Order(16000), new Order(17000))), new User("David", true, List.of(new Order(5000), new Order(20000), new Order(30000))), new User("Eve", true, List.of(new Order(10000), new Order(10000), new Order(10000), new Order(12000))) ); List<User> premiumUsers = new ArrayList<>(); for (User user : users) { if (user.isActive()) { int totalOrders = 0; for (Order order : user.getOrders()) { if (order.getTotal() >= 10000) { totalOrders++; } } if (totalOrders >= 3) { premiumUsers.add(user); } } } System.out.println("Premium users: " + premiumUsers); } } class Order { private final double total; public Order(double total) { this.total = total; } public double getTotal() { return total; } } class User { private final String name; private final boolean active; private final List<Order> orders; public User(String name, boolean active, List<Order> orders) { this.name = name; this.active = active; this.orders = orders; } public boolean isActive() { return active; } public List<Order> getOrders() { return orders; } @Override public String toString() { return "User{name='" + name + "'}"; } }

Je hebt twee belangrijke klassen:

Order vertegenwoordigt een bestelling en bevat een total-veld waarin het bedrag van de bestelling wordt opgeslagen. User vertegenwoordigt een winkelklant met drie velden:

  • name (naam van de gebruiker);
  • active (statusvlag);
  • orders (lijst van bestellingen).

Elke User bevat een lijst van Order-objecten, waarmee een realistische situatie wordt gemodelleerd waarin een klant meerdere bestellingen plaatst.

In main maak je een lijst van gebruikers, elk met hun eigen set bestellingen. Het programma loopt vervolgens door deze lijst en controleert of een gebruiker actief is. Zo niet, dan worden ze overgeslagen.

Vervolgens loopt het programma door de bestellingen van de gebruiker en telt hoeveel er $10.000 of meer zijn. Als de gebruiker minstens drie kwalificerende bestellingen heeft, worden ze toegevoegd aan de lijst premiumUsers.

Nadat alle gebruikers zijn verwerkt, print het programma de premiumgebruikers.

Problemen met de code

  • Te veel geneste lussen – maakt het moeilijker om te lezen en te begrijpen;
  • Overbodige code – te veel handmatige controles en tussentijdse variabelen;
  • Gebrek aan declaratieve stijl – de code voelt als laag-niveau gegevensverwerking in plaats van hoog-niveau logica.

Je gaat nu deze code stap voor stap herstructureren met behulp van de Stream API om de leesbaarheid te verbeteren, overbodigheid te verminderen en het efficiënter te maken.

Code Refactoring

De eerste stap is het verwijderen van de buitenste if (user.isActive()) en deze direct integreren in de Stream API:

List<User> premiumUsers = users.stream()
        .filter(User::isActive)  // Keep only active users
        .toList();

Nu is de code meer declaratief en laat duidelijk zien dat je actieve gebruikers filtert. De overbodige if-voorwaarde is verwijderd—de logica is nu direct ingebouwd in de Stream API. Dit is echter slechts datavoorbereiding, dus laten we verder gaan!

Vervolgens gaan we de geneste for-lus (for (Order order : user.getOrders())) vervangen door een stream() binnen de filter:

List<User> premiumUsers = users.stream()
        .filter(User::isActive)
        .filter(user -> user.getOrders().stream()
                .filter(order -> order.getTotal() >= 10000)
                .count() >= 3)  // Count orders directly in Stream API
        .toList();

Door handmatig tellen te elimineren, is de code overzichtelijker en leesbaarder geworden—nu verzorgt count() dit voor ons, waardoor we met de stream kunnen werken zonder extra variabelen.

Definitief Geherstructureerde Code

Nu is er een volledig geherstructureerde oplossing die de opdracht op een declaratieve en bondige wijze oplost:

Main.java

Main.java

copy
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<User> users = List.of( new User("Alice", true, List.of(new Order(12000), new Order(15000), new Order(11000))), new User("Bob", true, List.of(new Order(8000), new Order(9000), new Order(12000))), new User("Charlie", false, List.of(new Order(15000), new Order(16000), new Order(17000))), new User("David", true, List.of(new Order(5000), new Order(20000), new Order(30000))), new User("Eve", true, List.of(new Order(10000), new Order(10000), new Order(10000), new Order(12000))) ); List<User> premiumUsers = users.stream() .filter(User::isActive) .filter(user -> user.getOrders().stream() .filter(order -> order.getTotal() >= 10000) .count() >= 3) .toList(); System.out.println("Premium users: " + premiumUsers); } } class Order { private final double total; public Order(double total) { this.total = total; } public double getTotal() { return total; } } class User { private final String name; private final boolean active; private final List<Order> orders; public User(String name, boolean active, List<Order> orders) { this.name = name; this.active = active; this.orders = orders; } public boolean isActive() { return active; } public List<Order> getOrders() { return orders; } @Override public String toString() { return "User{name='" + name + "'}"; } }

De code is nu korter en duidelijker omdat, in plaats van een reeks handmatige controles, een declaratieve benadering wordt gebruikt—gericht op wat er moet gebeuren in plaats van elk detail van het proces te specificeren. Dit elimineert de noodzaak voor geneste lussen, waardoor de code eenvoudiger te lezen en te onderhouden is.

Door gebruik te maken van de Stream API worden filteren, tellen en gegevensverzameling naadloos gecombineerd in één enkele stream, waardoor de code expressiever en efficiënter wordt.

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 4. Hoofdstuk 1

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

bookPraktijkvoorbeelden van het Gebruik van Stream API

Veeg om het menu te tonen

Code draait niet alleen om functionaliteit—het gaat ook om leesbaarheid. Goed gestructureerde code is eenvoudiger te onderhouden, aan te passen en uit te breiden.

Je bent een ontwikkelaar die de taak heeft om de code van iemand anders te reviewen en te verbeteren. In echte projecten wordt code vaak in haast geschreven, gekopieerd uit verschillende delen van het programma, of simpelweg niet ontworpen met leesbaarheid als uitgangspunt. Jouw taak is niet alleen om de code te begrijpen, maar ook om deze te verbeteren—door deze netter, bondiger en eenvoudiger onderhoudbaar te maken.

Op dit moment voer je een code review uit. Je zult een echt stuk code analyseren, de zwakke punten identificeren en het stap voor stap herstructureren met behulp van de Stream API.

Aan de slag

Stel je hebt een online winkel en je moet actieve gebruikers identificeren die ten minste drie bestellingen van $10.000 of meer hebben geplaatst. Dit helpt het marketingteam om de meest waardevolle klanten te herkennen en hen gepersonaliseerde aanbiedingen te doen.

Hier is de oorspronkelijke code vóór het herstructureren:

Main.java

Main.java

copy
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<User> users = List.of( new User("Alice", true, List.of(new Order(12000), new Order(15000), new Order(11000))), new User("Bob", true, List.of(new Order(8000), new Order(9000), new Order(12000))), new User("Charlie", false, List.of(new Order(15000), new Order(16000), new Order(17000))), new User("David", true, List.of(new Order(5000), new Order(20000), new Order(30000))), new User("Eve", true, List.of(new Order(10000), new Order(10000), new Order(10000), new Order(12000))) ); List<User> premiumUsers = new ArrayList<>(); for (User user : users) { if (user.isActive()) { int totalOrders = 0; for (Order order : user.getOrders()) { if (order.getTotal() >= 10000) { totalOrders++; } } if (totalOrders >= 3) { premiumUsers.add(user); } } } System.out.println("Premium users: " + premiumUsers); } } class Order { private final double total; public Order(double total) { this.total = total; } public double getTotal() { return total; } } class User { private final String name; private final boolean active; private final List<Order> orders; public User(String name, boolean active, List<Order> orders) { this.name = name; this.active = active; this.orders = orders; } public boolean isActive() { return active; } public List<Order> getOrders() { return orders; } @Override public String toString() { return "User{name='" + name + "'}"; } }

Je hebt twee belangrijke klassen:

Order vertegenwoordigt een bestelling en bevat een total-veld waarin het bedrag van de bestelling wordt opgeslagen. User vertegenwoordigt een winkelklant met drie velden:

  • name (naam van de gebruiker);
  • active (statusvlag);
  • orders (lijst van bestellingen).

Elke User bevat een lijst van Order-objecten, waarmee een realistische situatie wordt gemodelleerd waarin een klant meerdere bestellingen plaatst.

In main maak je een lijst van gebruikers, elk met hun eigen set bestellingen. Het programma loopt vervolgens door deze lijst en controleert of een gebruiker actief is. Zo niet, dan worden ze overgeslagen.

Vervolgens loopt het programma door de bestellingen van de gebruiker en telt hoeveel er $10.000 of meer zijn. Als de gebruiker minstens drie kwalificerende bestellingen heeft, worden ze toegevoegd aan de lijst premiumUsers.

Nadat alle gebruikers zijn verwerkt, print het programma de premiumgebruikers.

Problemen met de code

  • Te veel geneste lussen – maakt het moeilijker om te lezen en te begrijpen;
  • Overbodige code – te veel handmatige controles en tussentijdse variabelen;
  • Gebrek aan declaratieve stijl – de code voelt als laag-niveau gegevensverwerking in plaats van hoog-niveau logica.

Je gaat nu deze code stap voor stap herstructureren met behulp van de Stream API om de leesbaarheid te verbeteren, overbodigheid te verminderen en het efficiënter te maken.

Code Refactoring

De eerste stap is het verwijderen van de buitenste if (user.isActive()) en deze direct integreren in de Stream API:

List<User> premiumUsers = users.stream()
        .filter(User::isActive)  // Keep only active users
        .toList();

Nu is de code meer declaratief en laat duidelijk zien dat je actieve gebruikers filtert. De overbodige if-voorwaarde is verwijderd—de logica is nu direct ingebouwd in de Stream API. Dit is echter slechts datavoorbereiding, dus laten we verder gaan!

Vervolgens gaan we de geneste for-lus (for (Order order : user.getOrders())) vervangen door een stream() binnen de filter:

List<User> premiumUsers = users.stream()
        .filter(User::isActive)
        .filter(user -> user.getOrders().stream()
                .filter(order -> order.getTotal() >= 10000)
                .count() >= 3)  // Count orders directly in Stream API
        .toList();

Door handmatig tellen te elimineren, is de code overzichtelijker en leesbaarder geworden—nu verzorgt count() dit voor ons, waardoor we met de stream kunnen werken zonder extra variabelen.

Definitief Geherstructureerde Code

Nu is er een volledig geherstructureerde oplossing die de opdracht op een declaratieve en bondige wijze oplost:

Main.java

Main.java

copy
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<User> users = List.of( new User("Alice", true, List.of(new Order(12000), new Order(15000), new Order(11000))), new User("Bob", true, List.of(new Order(8000), new Order(9000), new Order(12000))), new User("Charlie", false, List.of(new Order(15000), new Order(16000), new Order(17000))), new User("David", true, List.of(new Order(5000), new Order(20000), new Order(30000))), new User("Eve", true, List.of(new Order(10000), new Order(10000), new Order(10000), new Order(12000))) ); List<User> premiumUsers = users.stream() .filter(User::isActive) .filter(user -> user.getOrders().stream() .filter(order -> order.getTotal() >= 10000) .count() >= 3) .toList(); System.out.println("Premium users: " + premiumUsers); } } class Order { private final double total; public Order(double total) { this.total = total; } public double getTotal() { return total; } } class User { private final String name; private final boolean active; private final List<Order> orders; public User(String name, boolean active, List<Order> orders) { this.name = name; this.active = active; this.orders = orders; } public boolean isActive() { return active; } public List<Order> getOrders() { return orders; } @Override public String toString() { return "User{name='" + name + "'}"; } }

De code is nu korter en duidelijker omdat, in plaats van een reeks handmatige controles, een declaratieve benadering wordt gebruikt—gericht op wat er moet gebeuren in plaats van elk detail van het proces te specificeren. Dit elimineert de noodzaak voor geneste lussen, waardoor de code eenvoudiger te lezen en te onderhouden is.

Door gebruik te maken van de Stream API worden filteren, tellen en gegevensverzameling naadloos gecombineerd in één enkele stream, waardoor de code expressiever en efficiënter wordt.

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 4. Hoofdstuk 1
some-alt