Ytelse i Stream API
Du har refaktorert koden og gjort den renere, kortere og mer uttrykkende.
Men hva med ytelse? Hvor effektiv er Stream API sammenlignet med tradisjonelle løkker? Kan du øke hastigheten ved å bruke parallelStream()? La oss finne det ut!
Måling av kjøretid
For å sammenligne ytelse objektivt, opprettes et testdatasett med 100 000 brukere og ulike ordrer. Deretter implementeres tre filtreringsmetoder:
- Tradisjonell
for-loop– en klassisk metode med nøstede løkker; - Stream API (
stream()) – en moderne deklarativ metode; - Parallel Stream API (
parallelStream()) – flertrådet prosessering.
Kjøretid måles med System.nanoTime(), som gir høypresisjons tidsforskjeller.
Testimplementasjon
Det genereres 100 000 brukere, alle med ordrer over $10,000, og alle tre metodene kjøres for å se hvilken som gir best ytelse.
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 + "'}"; } }
Etter å ha kjørt testen med 100,000 users, kan du observere følgende trender:
Tradisjonell for-loop er raskere for enkle operasjoner siden den unngår overhead fra opprettelse av strømmer og ekstra objekter. Den gir best ytelse når rå hastighet er prioritert.
Stream API er noen ganger litt saktere på grunn av ekstra strømobjekter, men forbedrer betydelig lesbarhet og vedlikeholdbarhet i koden.
Parallel Stream API kan øke prosesseringshastigheten på flerkjernede systemer, men ikke alltid. Hvis datasettet er lite, kan overhead ved trådhåndtering faktisk senke hastigheten. Den fungerer best for tunge beregninger, men ikke når man endrer delte variabler, siden trådene kjører uavhengig.
Sammendrag
Stream API er et kraftig verktøy som gjør koden mer lesbar og konsis. Når det gjelder ytelse, er det imidlertid viktig å forstå dets begrensninger. I noen tilfeller er tradisjonelle for-løkker raskere, spesielt når man arbeider med små datasett. parallelStream() kan forbedre behandlingshastigheten, men det krever testing for å sikre at det faktisk gir en fordel.
Valg av riktig tilnærming bør derfor være bevisst: hvis lesbarhet er en prioritet, bruk Stream API; hvis ytelse er kritisk, test og mål!
1. Hvilken tilnærming er vanligvis den raskeste for enkle operasjoner?
2. Hvorfor kan Stream API være tregere enn en vanlig løkke?
3. Når kan parallelStream() redusere ytelsen?
Takk for tilbakemeldingene dine!
Spør AI
Spør AI
Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår
Awesome!
Completion rate improved to 2.33
Ytelse i Stream API
Sveip for å vise menyen
Du har refaktorert koden og gjort den renere, kortere og mer uttrykkende.
Men hva med ytelse? Hvor effektiv er Stream API sammenlignet med tradisjonelle løkker? Kan du øke hastigheten ved å bruke parallelStream()? La oss finne det ut!
Måling av kjøretid
For å sammenligne ytelse objektivt, opprettes et testdatasett med 100 000 brukere og ulike ordrer. Deretter implementeres tre filtreringsmetoder:
- Tradisjonell
for-loop– en klassisk metode med nøstede løkker; - Stream API (
stream()) – en moderne deklarativ metode; - Parallel Stream API (
parallelStream()) – flertrådet prosessering.
Kjøretid måles med System.nanoTime(), som gir høypresisjons tidsforskjeller.
Testimplementasjon
Det genereres 100 000 brukere, alle med ordrer over $10,000, og alle tre metodene kjøres for å se hvilken som gir best ytelse.
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 + "'}"; } }
Etter å ha kjørt testen med 100,000 users, kan du observere følgende trender:
Tradisjonell for-loop er raskere for enkle operasjoner siden den unngår overhead fra opprettelse av strømmer og ekstra objekter. Den gir best ytelse når rå hastighet er prioritert.
Stream API er noen ganger litt saktere på grunn av ekstra strømobjekter, men forbedrer betydelig lesbarhet og vedlikeholdbarhet i koden.
Parallel Stream API kan øke prosesseringshastigheten på flerkjernede systemer, men ikke alltid. Hvis datasettet er lite, kan overhead ved trådhåndtering faktisk senke hastigheten. Den fungerer best for tunge beregninger, men ikke når man endrer delte variabler, siden trådene kjører uavhengig.
Sammendrag
Stream API er et kraftig verktøy som gjør koden mer lesbar og konsis. Når det gjelder ytelse, er det imidlertid viktig å forstå dets begrensninger. I noen tilfeller er tradisjonelle for-løkker raskere, spesielt når man arbeider med små datasett. parallelStream() kan forbedre behandlingshastigheten, men det krever testing for å sikre at det faktisk gir en fordel.
Valg av riktig tilnærming bør derfor være bevisst: hvis lesbarhet er en prioritet, bruk Stream API; hvis ytelse er kritisk, test og mål!
1. Hvilken tilnærming er vanligvis den raskeste for enkle operasjoner?
2. Hvorfor kan Stream API være tregere enn en vanlig løkke?
3. Når kan parallelStream() redusere ytelsen?
Takk for tilbakemeldingene dine!