java 8 lambda遍历和增强for循环的效率哪个快?

前面讲list转树形结构的时候,由于业务原因无法使用最快的方法,导致很慢,今天就研究在循环上提升速度。
Java8 lambda遍历出来后有人说它快有人说它要慎用?到底怎么回事让我们来一探究竟吧!看不懂可以先看后面的分析

测试代码:

package cn.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++) {
            test(list.get(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++) {
            list.get(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
增强for					162.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
增强for					13.1 ms
java8 foreach			8.6 ms
java8 Stream foreach	11.1 ms

-----------预热情况  次数:250------------
fori					50.6 ms
增强for					63.4 ms
java8 foreach			32.1 ms
java8 Stream foreach	34.5 ms

-----------预热情况  次数:1000------------
fori					205.9 ms
增强for					255.9 ms
java8 foreach			101.9 ms
java8 Stream foreach	74.7 ms

-----------预热情况  次数:2000------------
fori					142.1 ms
增强for					322.8 ms
java8 foreach			164.5 ms
java8 Stream foreach	153.5 ms

-----------预热情况  次数:3000------------
fori					193.9 ms
增强for					167.5 ms
java8 foreach			136.8 ms
java8 Stream foreach	118.0 ms

-----------预热情况  次数:5000------------
fori					154.1 ms
增强for					125.2 ms
java8 foreach			98.7 ms
java8 Stream foreach	73.8 ms

-----------预热情况  次数:10000------------
fori					263.6 ms
增强for					196.3 ms
java8 foreach			131.5 ms
java8 Stream foreach	163.1 ms

-----------预热情况  次数:20000------------
fori					417.3 ms
增强for					411.6 ms
java8 foreach			593.4 ms
java8 Stream foreach	476.9 ms

分析:我这里测试用了4种for循环
从第一个结果来看在jvm不预热的情况下lambda遍历方式反而花费的时间更长(jvm预热可以单独去查看是什么意思)
从后面的结果来看在jvm预热的情况下,并且数据量大的情况下lambda遍历方式花费的时间少一些,我这里没用使用Stream接口里面的方法,所以foreach比Stream().forEach快一些

你可能感兴趣的:(java8新特性,java8遍历,java8,java)