Leistung in Stream-API
Sie haben den Code erfolgreich umgestaltet und ihn übersichtlicher, kürzer und ausdrucksstärker gemacht.
Aber wie steht es um die Leistung? Wie effizient ist die Stream-API im Vergleich zu herkömmlichen Schleifen? Können Sie die Ausführung mit parallelStream() beschleunigen? Finden wir es heraus!
Ausführungszeit messen
Um die Leistung objektiv zu vergleichen, wird ein Testdatensatz mit 100.000 Benutzern und verschiedenen Bestellungen erstellt. Anschließend werden drei Filtermethoden implementiert:
- Traditionelle
for-loop– ein klassischer Ansatz mit verschachtelten Schleifen; - Stream-API (
stream()) – eine moderne deklarative Methode; - Parallele Stream-API (
parallelStream()) – mehrfädige Verarbeitung.
Die Ausführungszeit wird mit System.nanoTime() gemessen, das hochpräzise Zeitdifferenzen liefert.
Testimplementierung
Es werden 100.000 Benutzer generiert, wobei sichergestellt wird, dass alle Bestellungen über $10.000 liegen, und alle drei Methoden werden ausgeführt, um festzustellen, welche die beste Leistung erbringt.
Main.java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<User> users = generateUsers(100000); // Measuring traditional loop execution time long startTime = System.nanoTime(); List<User> premiumUsersLoop = 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) { premiumUsersLoop.add(user); } } } long endTime = System.nanoTime(); System.out.println("For-loop: " + (endTime - startTime) / 1_000_000 + " ms"); // Measuring Stream API execution time startTime = System.nanoTime(); List<User> premiumUsersStream = users.stream() .filter(User::isActive) .filter(user -> user.getOrders().stream() .filter(order -> order.getTotal() >= 10000) .count() >= 3) .toList(); endTime = System.nanoTime(); System.out.println("Stream API: " + (endTime - startTime) / 1_000_000 + " ms"); // Measuring Parallel Stream API execution time startTime = System.nanoTime(); List<User> premiumUsersParallelStream = users.parallelStream() .filter(User::isActive) .filter(user -> user.getOrders().stream() .filter(order -> order.getTotal() >= 10000) .count() >= 3) .toList(); endTime = System.nanoTime(); System.out.println("Parallel Stream API: " + (endTime - startTime) / 1_000_000 + " ms"); } private static List<User> generateUsers(int count) { List<User> users = new ArrayList<>(); for (int i = 0; i < count; i++) { users.add(new User("User" + i, true, List.of( new Order(14000), new Order(5000), new Order(7000) ))); } return users; } } 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 + "'}"; } }
Nach dem Ausführen des Tests mit 100.000 Benutzern lassen sich folgende Tendenzen beobachten:
Die traditionelle for-loop ist bei einfachen Operationen schneller, da sie keinen Overhead durch die Erstellung von Streams und zusätzlichen Objekten verursacht. Sie erzielt die besten Ergebnisse, wenn maximale Geschwindigkeit im Vordergrund steht.
Die Stream-API ist manchmal etwas langsamer aufgrund zusätzlicher Stream-Objekte, verbessert jedoch die Lesbarkeit und Wartbarkeit des Codes erheblich.
Die Parallel Stream-API kann die Verarbeitung auf Mehrkernsystemen beschleunigen, aber nicht immer. Ist der Datensatz klein, kann der Overhead für das Thread-Management tatsächlich zu einer Verlangsamung führen. Sie eignet sich am besten für rechenintensive Aufgaben, jedoch nicht bei der Modifikation von gemeinsam genutzten Variablen, da Threads unabhängig voneinander ausgeführt werden.
Zusammenfassung
Die Stream API ist ein leistungsstarkes Werkzeug, das Code lesbarer und prägnanter macht. Hinsichtlich der Performance ist es jedoch wichtig, ihre Einschränkungen zu verstehen. In manchen Fällen sind traditionelle for-Schleifen schneller, insbesondere bei kleinen Datensätzen. parallelStream() kann die Verarbeitungsgeschwindigkeit erhöhen, erfordert jedoch Tests, um sicherzustellen, dass tatsächlich ein Vorteil entsteht.
Die Wahl des richtigen Ansatzes sollte daher bewusst erfolgen: Wenn Lesbarkeit im Vordergrund steht, die Stream API verwenden; wenn Performance entscheidend ist, testen und messen!
1. Welcher Ansatz ist typischerweise der schnellste für einfache Operationen?
2. Warum kann die Stream API langsamer sein als eine normale Schleife?
3. Wann kann parallelStream() die Ausführung verlangsamen?
Danke für Ihr Feedback!
Fragen Sie AI
Fragen Sie AI
Fragen Sie alles oder probieren Sie eine der vorgeschlagenen Fragen, um unser Gespräch zu beginnen
Can you explain when it's best to use Stream API versus traditional loops?
How does parallelStream() actually work under the hood?
What are some real-world scenarios where parallelStream() would be beneficial?
Awesome!
Completion rate improved to 2.33
Leistung in Stream-API
Swipe um das Menü anzuzeigen
Sie haben den Code erfolgreich umgestaltet und ihn übersichtlicher, kürzer und ausdrucksstärker gemacht.
Aber wie steht es um die Leistung? Wie effizient ist die Stream-API im Vergleich zu herkömmlichen Schleifen? Können Sie die Ausführung mit parallelStream() beschleunigen? Finden wir es heraus!
Ausführungszeit messen
Um die Leistung objektiv zu vergleichen, wird ein Testdatensatz mit 100.000 Benutzern und verschiedenen Bestellungen erstellt. Anschließend werden drei Filtermethoden implementiert:
- Traditionelle
for-loop– ein klassischer Ansatz mit verschachtelten Schleifen; - Stream-API (
stream()) – eine moderne deklarative Methode; - Parallele Stream-API (
parallelStream()) – mehrfädige Verarbeitung.
Die Ausführungszeit wird mit System.nanoTime() gemessen, das hochpräzise Zeitdifferenzen liefert.
Testimplementierung
Es werden 100.000 Benutzer generiert, wobei sichergestellt wird, dass alle Bestellungen über $10.000 liegen, und alle drei Methoden werden ausgeführt, um festzustellen, welche die beste Leistung erbringt.
Main.java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<User> users = generateUsers(100000); // Measuring traditional loop execution time long startTime = System.nanoTime(); List<User> premiumUsersLoop = 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) { premiumUsersLoop.add(user); } } } long endTime = System.nanoTime(); System.out.println("For-loop: " + (endTime - startTime) / 1_000_000 + " ms"); // Measuring Stream API execution time startTime = System.nanoTime(); List<User> premiumUsersStream = users.stream() .filter(User::isActive) .filter(user -> user.getOrders().stream() .filter(order -> order.getTotal() >= 10000) .count() >= 3) .toList(); endTime = System.nanoTime(); System.out.println("Stream API: " + (endTime - startTime) / 1_000_000 + " ms"); // Measuring Parallel Stream API execution time startTime = System.nanoTime(); List<User> premiumUsersParallelStream = users.parallelStream() .filter(User::isActive) .filter(user -> user.getOrders().stream() .filter(order -> order.getTotal() >= 10000) .count() >= 3) .toList(); endTime = System.nanoTime(); System.out.println("Parallel Stream API: " + (endTime - startTime) / 1_000_000 + " ms"); } private static List<User> generateUsers(int count) { List<User> users = new ArrayList<>(); for (int i = 0; i < count; i++) { users.add(new User("User" + i, true, List.of( new Order(14000), new Order(5000), new Order(7000) ))); } return users; } } 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 + "'}"; } }
Nach dem Ausführen des Tests mit 100.000 Benutzern lassen sich folgende Tendenzen beobachten:
Die traditionelle for-loop ist bei einfachen Operationen schneller, da sie keinen Overhead durch die Erstellung von Streams und zusätzlichen Objekten verursacht. Sie erzielt die besten Ergebnisse, wenn maximale Geschwindigkeit im Vordergrund steht.
Die Stream-API ist manchmal etwas langsamer aufgrund zusätzlicher Stream-Objekte, verbessert jedoch die Lesbarkeit und Wartbarkeit des Codes erheblich.
Die Parallel Stream-API kann die Verarbeitung auf Mehrkernsystemen beschleunigen, aber nicht immer. Ist der Datensatz klein, kann der Overhead für das Thread-Management tatsächlich zu einer Verlangsamung führen. Sie eignet sich am besten für rechenintensive Aufgaben, jedoch nicht bei der Modifikation von gemeinsam genutzten Variablen, da Threads unabhängig voneinander ausgeführt werden.
Zusammenfassung
Die Stream API ist ein leistungsstarkes Werkzeug, das Code lesbarer und prägnanter macht. Hinsichtlich der Performance ist es jedoch wichtig, ihre Einschränkungen zu verstehen. In manchen Fällen sind traditionelle for-Schleifen schneller, insbesondere bei kleinen Datensätzen. parallelStream() kann die Verarbeitungsgeschwindigkeit erhöhen, erfordert jedoch Tests, um sicherzustellen, dass tatsächlich ein Vorteil entsteht.
Die Wahl des richtigen Ansatzes sollte daher bewusst erfolgen: Wenn Lesbarkeit im Vordergrund steht, die Stream API verwenden; wenn Performance entscheidend ist, testen und messen!
1. Welcher Ansatz ist typischerweise der schnellste für einfache Operationen?
2. Warum kann die Stream API langsamer sein als eine normale Schleife?
3. Wann kann parallelStream() die Ausführung verlangsamen?
Danke für Ihr Feedback!