Rajkishan Rajkishan - 22 days ago 8
Java Question

Java 8 forEach Stream() vs old forEach Loop

I was trying a example code with spring. And a part of code is like below;

private List<Point> points;
long timeTakeninMilis = System.currentTimeMillis();

public List<Point> getPoints() {
return points;
}

public void setPoints(List<Point> points) {
this.points = points;
}

public void drawJava8() {
points.stream().forEachOrdered(
point -> System.out.println("Point : (" + point.getX() + ", "
+ point.getY() + ")"));
System.out.println("Total Time Taken drawJava8(): "
+ (System.currentTimeMillis() - timeTakeninMilis)
+ " miliseconds");
}

public void draw() {
for (Point point : points) {
System.out.println("Point = (" + point.getX() + ", " + point.getY()
+ " )");

}
System.out.println("Total Time Taken draw(): "
+ (System.currentTimeMillis() - timeTakeninMilis)
+ " miliseconds");
}


The OUTPUT,

Jun 30, 2015 11:30:53 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7daf6ecc: startup date [Tue Jun 30 11:30:53 IST 2015]; root of context hierarchy
Jun 30, 2015 11:30:53 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring.xml]
Point = (0, 0 )
Point = (-50, 0 )
Point = (0, 50 )
Total Time Taken draw(): 70 miliseconds
Point : (0, 0)
Point : (-50, 0)
Point : (0, 50)
Total Time Taken drawJava8(): 124 miliseconds
Jun 30, 2015 11:30:54 AM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@7daf6ecc: startup date [Tue Jun 30 11:30:53 IST 2015]; root of context hierarchy


Why it is taking more time?
Or i am doing something wrong?

I was expecting it to be faster or of similar speed...
Please help me understand what is the benefit of the Lambda Expressions?

INFO: I did it in two different programs. Times are taken from those. I merged them here to make it short.

Answer

Adding this as an analysis per original poster's request.

We can not really predict the sophisticated analysis and transformation that the modern JIT compiler performs on running code. Hence while benchmarking items such as these, you should not conclude it just by running two method calls.

Instead, create various sample input sets (boundary cases) and check the perofmance by repeatedly calling your test cases without shutting down JVM. In this case for example :

for (int i=0;i<100;i++){draw(); drawJava8();}

Once you have the results, find out average execution and you can safely ignore first execution result as it might not have had optimizations.

So the conclusion you have drawn from your tests is not completely correct.