As stated in the comments: you can hardly draw any conclusion from such a simple, simple and isolated launch of microbusiness.
Partially refers to another (otherwise unrelated) answer :
There are several options for correct and reliable runtime measurement. Besides a profiler like VisualVM , there are frameworks like JMH or Caliper , but admittedly using them can be a bit of an effort.
For the simplest form of a very simple manual Java Microbenchmark, you should consider the following:
- Run the algorithms several times to give JIT the ability to hit
- Run algorithms one at a time, and not just one after another
- Running algorithms with increasing input size
- Somehow save and print the calculation results to prevent optimization of the calculations.
- Consider Timings May Be Distorted By The Garbage Collector (GC)
These are just rules of thumb , and there may still be unexpected results (see the links above for more details). But with this strategy, you usually get a good idea of performance, and at least you can see if there are significant differences between the algorithms.
Related reading:
I applied these basic steps to your program. Here is the MCVE :
NOTE. The rest was updated in response to the subsequent editing of the question)
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.stream.Collectors; class Person { public static final int MALE = 0; public static final int FEMALE = 1; private final String name; private final int sex; private final int age; public Person(String name, int sex, int age) { this.name = name; this.sex = sex; this.age = age; } public int getSex() { return sex; } public int getAge() { return age; } } public class Main { public static void main(String[] args) { new Main(); } private List<Person> people; public Main() { for (int size=10; size<=1000000; size*=10) { Random r = new Random(0); people = new ArrayList<Person>(); for (int i = 0; i < size; i++) { int s = r.nextInt(2); int a = 25 + r.nextInt(20); people.add(new Person("p" + i, s, a)); } int min = 10000000 / size; int max = 10 * min; for (int n = min; n <= max; n += min) { lambdaMethodUsingForEach(n); lambdaMethodUsingCollect(n); defaultMethod(n); } } } public void lambdaMethodUsingForEach(int n) { List<Person> lambdaOutput = new ArrayList<Person>(); long lambdaStart = System.currentTimeMillis(); for (int i = 0; i < n; i++) { lambdaOutput.addAll(getFemaleYoungAdultsUsingLambdaUsingForEach()); } System.out.printf("List size: %10d, runs: %10d, result: %10d, ForEach took: " + (System.currentTimeMillis() - lambdaStart) + " ms\n", people.size(), n, lambdaOutput.size()); } public void lambdaMethodUsingCollect(int n) { List<Person> lambdaOutput = new ArrayList<Person>(); long lambdaStart = System.currentTimeMillis(); for (int i = 0; i < n; i++) { lambdaOutput.addAll(getFemaleYoungAdultsUsingLambdaUsingCollect()); } System.out.printf("List size: %10d, runs: %10d, result: %10d, collect took: " + (System.currentTimeMillis() - lambdaStart) + " ms\n", people.size(), n, lambdaOutput.size()); } public void defaultMethod(int n) { List<Person> defaultOutput = new ArrayList<Person>(); long defaultStart = System.currentTimeMillis(); for (int i = 0; i < n; i++) { defaultOutput.addAll(getFemaleYoungAdultsUsingFunctions()); } System.out.printf("List size: %10d, runs: %10d, result: %10d, default took: " + (System.currentTimeMillis() - defaultStart) + " ms\n", people.size(), n, defaultOutput.size()); } public List<Person> getFemaleYoungAdultsUsingLambdaUsingForEach() { List<Person> people = new ArrayList<Person>(); this.people.stream().filter( (p) -> p.getSex() == Person.FEMALE && p.getAge() >= 18 && p.getAge() <= 25).forEach(people::add); return people; } public List<Person> getFemaleYoungAdultsUsingLambdaUsingCollect() { return this.people.stream().filter( (p) -> p.getSex() == Person.FEMALE && p.getAge() >= 18 && p.getAge() <= 25).collect(Collectors.toList()); } public List<Person> getFemaleYoungAdultsUsingFunctions() { List<Person> people = new ArrayList<Person>(); for (Person p : this.people) { if (p.getSex() == Person.FEMALE && p.getAge() >= 18 && p.getAge() <= 25) { people.add(p); } } return people; } }
The output to My Machine® corresponds to the following lines:
... List size: 10, runs: 10000000, result: 10000000, ForEach took: 1482 ms List size: 10, runs: 10000000, result: 10000000, collect took: 2014 ms List size: 10, runs: 10000000, result: 10000000, default took: 1013 ms ... List size: 100, runs: 1000000, result: 3000000, ForEach took: 664 ms List size: 100, runs: 1000000, result: 3000000, collect took: 515 ms List size: 100, runs: 1000000, result: 3000000, default took: 441 ms ... List size: 1000, runs: 100000, result: 2300000, ForEach took: 778 ms List size: 1000, runs: 100000, result: 2300000, collect took: 721 ms List size: 1000, runs: 100000, result: 2300000, default took: 841 ms ... List size: 10000, runs: 10000, result: 2450000, ForEach took: 970 ms List size: 10000, runs: 10000, result: 2450000, collect took: 971 ms List size: 10000, runs: 10000, result: 2450000, default took: 1119 ms ... List size: 100000, runs: 1000, result: 2536000, ForEach took: 976 ms List size: 100000, runs: 1000, result: 2536000, collect took: 1057 ms List size: 100000, runs: 1000, result: 2536000, default took: 1109 ms ... List size: 1000000, runs: 100, result: 2488600, ForEach took: 1323 ms List size: 1000000, runs: 100, result: 2488600, collect took: 1305 ms List size: 1000000, runs: 100, result: 2488600, default took: 1422 ms
You can see that the difference between ForEach and default approaches (public methods) disappears even for small lists. For larger lists, there seems to be a slight advantage for lambda oriented approaches.
To emphasize this again: this micro-tag is very simple , and even this does not necessarily indicate the performance of these approaches in practice. However, it’s at least reasonable to assume that the difference between ForEach and public methods is small, as suggested by your initial test. Nevertleless: +1 from me for those who run this in JMH or Caliper and post some additional information about it.