java8lambda遍历和增强for循环的效率哪个快?
java stream前⾯讲list转树形结构的时候,由于业务原因⽆法使⽤最快的⽅法,导致很慢,今天就研究在循环上提升速度。
Java8 lambda遍历出来后有⼈说它快有⼈说它要慎⽤?到底怎么回事让我们来⼀探究竟吧!看不懂可以先看后⾯的分析测试代码:
package cncommdata.zhonglvreport;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public class ForiForeachJava8ForeachTest {
public static void main(String[] args){
// 预热
List<Dog> tmpList =listDog(10);
long time1 = System.nanoTime();
testFori(tmpList);
long time2 = System.nanoTime();
testForeach(tmpList);
long time3 = System.nanoTime();
testJava8ForEach(tmpList);
long time4 = System.nanoTime();
System.out.println("for2\t\t\t\t"+(int)(time2 - time1)/1000.0+" ms");
System.out.println("增强for\t\t\t\t"+(int)(time3 - time2)/1000.0+" ms");
System.out.println("java8 foreach\t\t"+(int)(time4 - time3)/1000.0+" ms");
List<Integer> list = Arrays.asList(10,50,250,1000,2000,3000,5000,10000,20000);
for(int i =0; i < list.size(); i++){
(i));
}
}
public static void test(int size){
System.out.println("-----------次数:"+ size +"------------");
List<Dog> list =listDog(size);
long nanoTime = System.nanoTime();
testFori(list);
long nanoTime1 = System.nanoTime();
testForeach(list);
long nanoTime2 = System.nanoTime();
testJava8ForEach(list);
long nanoTime3 = System.nanoTime();
testJava8ForEachStream(list);
long nanoTime4 = System.nanoTime();
System.out.println("fori\t\t\t\t"+(int)(nanoTime1 - nanoTime)/1000.0+" ms");
System.out.println("增强for\t\t\t\t"+(int)(nanoTime2 - nanoTime1)/1000.0+" ms");
System.out.println("java8 foreach\t\t"+(int)(nanoTime3 - nanoTime2)/1000.0+" ms");
System.out.println("java8 Stream foreach\t\t"+(int)(nanoTime4 - nanoTime3)/1000.0+" ms");
System.out.println();
}
/**
* 初始化list
*
* @param size int
* @return list
*/
public static List<Dog>listDog(int size){
List<Dog> list =new ArrayList<>();
for(int i =0; i < size; i++){
list.add(new Dog(i +1,"dog "+(i +1)));
}
return list;
}
/**
* 测试fori
*
* @param list List
*/
public static void testFori(List<Dog> list){
for(int i =0; i < list.size(); i++){
<(i).hashCode();
}
}
/**
* 测试增强for循环
*
* @param list List
*/
public static void testForeach(List<Dog> list){
for(Dog dog : list){
dog.hashCode();
}
}
/**
* 测试java8的foreach
*
* @param list List
*/
public static void testJava8ForEach(List<Dog> list){
list.forEach(dog -> dog.hashCode());
}
/**
* 测试java8的foreach
*
* @param list List
*/
public static void testJava8ForEachStream(List<Dog> list){        list.stream().forEach(dog -> dog.hashCode());
}
}
/**
* 测试实体类,⽤来计算hashCode
*/
class Dog {
private int age;
private String name;
public Dog(int age, String name){
this.age = age;
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
@Override
public int hashCode(){
int result =17;
result =31* result + age;
result =31* result +(name == null ?0: name.hashCode());
return result;
}
@Override
public boolean equals(Object obj){
if(obj ==this){
return true;
}
if(!(obj instanceof Dog)){
return false;
}
Dog dog =(Dog) obj;
return dog.age ==this.age &&
Objects.equals(dog.name,this.name);
}
}
运⾏结果:
-------不预热的情况下-------
for2    13.5 ms
增强for162.5 ms
java8 foreach  41539.1 ms
java8 Stream foreach 2365.4 ms
-
----------预热情况次数:10------------
fori    3.6 ms
增强for  4.7 ms
java8 foreach  3.8 ms
java8 Stream foreach 6.9 ms
-----------预热情况次数:50------------
fori    9.7 ms
增强for13.1 ms
java8 foreach  8.6 ms
java8 Stream foreach 11.1 ms
-----------预热情况次数:250------------
fori    50.6 ms
增强for63.4 ms
java8 foreach  32.1 ms
java8 Stream foreach 34.5 ms
-----------预热情况次数:1000------------
fori    205.9 ms
增强for255.9 ms
java8 foreach  101.9 ms
java8 Stream foreach 74.7 ms
-----------预热情况次数:2000------------
fori    142.1 ms
增强for322.8 ms
java8 foreach  164.5 ms
java8 Stream foreach 153.5 ms
-----------预热情况次数:3000------------
fori    193.9 ms
增强for167.5 ms
java8 foreach  136.8 ms
java8 Stream foreach 118.0 ms
-----------预热情况次数:5000------------
fori    154.1 ms
增强for125.2 ms
java8 foreach  98.7 ms
java8 Stream foreach 73.8 ms
-----------预热情况次数:10000------------
fori    263.6 ms
增强for196.3 ms
java8 foreach  131.5 ms
java8 Stream foreach 163.1 ms
-----------预热情况次数:20000------------
fori    417.3 ms
增强for411.6 ms
java8 foreach  593.4 ms
java8 Stream foreach 476.9 ms
分析:我这⾥测试⽤了4种for循环
从第⼀个结果来看在jvm不预热的情况下lambda遍历⽅式反⽽花费的时间更长(jvm预热可以单独去查看是什么意思)
从后⾯的结果来看在jvm预热的情况下,并且数据量⼤的情况下lambda遍历⽅式花费的时间少⼀些,我这⾥没⽤使⽤Stream接⼝⾥⾯的⽅法,所以foreach⽐Stream().forEach快⼀些