for i和for each和Java8的forEach性能测试,到底谁快的测试

有说这个快,有说那个快,但是,靠嘴不顶用啊。还是测试一下就知道啦。

(Lists.newArrayList(); 这个是guava里面的一个集合初始化的工具)

如下 :

先是main方法吧

    /**
     * 测试不同for的效率问题
     */
    @Test
    public void testForEfficiency() {
        String[] array = CollectionUtil.getArray(SIZE);
        List<String> arrayList = CollectionUtil.getArrayList(SIZE);
        List<String> linkedList = CollectionUtil.getLinkedList(SIZE);

        while (true) {
            //array 0.5% 0.5%
            testArray(array);
            //for each : for i : lambda = 1.2% : 0.8% : 0.9%
            testArrayList(arrayList);
            //for each : for i : lambda = 1.2% : 94% : 0.9%
            testLinkedList(linkedList);
        }

    }

    /**
     * array 在使用forI循环的效率测试
     * 对数组来说,for i 和for each 效率是一样的
     */
    private static void testArray(String[] array) {
        testForI(array);
        testForEach(array);
    }

    /**
     * arrayList 在使用forI循环,forEach循环和lambda循环的效率测试
     */
    private static void testArrayList(List<String> arrayList) {
        testForI(arrayList);
        testForEach(arrayList);
        testLambda(arrayList);
    }

    /**
     * linkedList 在使用forI循环,forEach循环和lambda循环的效率测试
     */
    private static void testLinkedList(List<String> linkedList) {
        testForI(linkedList);
        testForEach(linkedList);
        testLambda(linkedList);
    }

    private static void testForI(String[] array) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < SIZE; i++) {
            sb.append(array[i]);
        }
    }

    private static void testForEach(String[] array) {
        StringBuilder sb = new StringBuilder();
        for (String s : array) {
            sb.append(s);
        }
    }
    private static void testForI(List<String> arrayList) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < SIZE; i++) {
            sb.append(arrayList.get(i));
        }
    }

    private static void testForEach(List<String> arrayList) {
        StringBuilder sb = new StringBuilder();
        for (String s : arrayList) {
            sb.append(s);
        }
    }

    private static void testLambda(List<String> arrayList) {
        StringBuilder sb = new StringBuilder();
        arrayList.forEach(sb::append);
    }

然后是获取2个集合的方法。

    /**
     * 获得底层是数组的list集合
     */
    public static List<String> getArrayList(Integer size) {
        size = (size == null || size <= 0) ? DEFAULT_SIZE : size;
        List<String> list = Lists.newArrayListWithExpectedSize(size);
        for (int i = 0; i < size; i++) {
            list.add(i + "1234567890");
        }
        return list;
    }

    /**
     * 获得底层是数组的数组
     */
    public static String[] getArray(Integer size) {
        size = (size == null || size <= 0) ? DEFAULT_SIZE : size;
        String[] array = new String[size];
        for (int i = 0; i < size; i++) {
            array[i] = (i + "1234567890");
        }
        return array;
    }

    /**
     * 获得底层是链表的list集合
     */
    public static List<String> getLinkedList(Integer size) {
        size = (size == null || size <= 0) ? DEFAULT_SIZE : size;
        List<String> list = Lists.newLinkedList();
        for (int i = 0; i < size; i++) {
            list.add(i + "1234567890");
        }
        return list;
    }

然后就是代码实际运行的结果图,jprofile的时间占比图

也就放这么几次的执行结果吧,有兴趣的可以自己跑一下。

为什么:

    for each是jdk5.0新增加的一个循环结构,可以用来处理集合中的每个元素而不用考虑集合定下标。
    格式就不说了

循环的集合:collection必须是一个数组或者是一个实现了lterable接口的类对象。
(Iterator<E> iterator(); List 集合实现了这个接口,它的子类当然也实现了,好吧collection也是实现的,所以这里可以看到的集合都可以用for each)
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
使用for each循环语句的优势在于更加简洁,更不容易出错,不必关心下标的起始值和终止值。
forEach不是关键字,关键字还是for,语句是由iterator实现的,他们最大的不同之处就在于remove()方法上。

 一般调用删除和添加方法都是具体集合的方法,例如:
List list = new ArrayList(); list.add(...); list.remove(...);
但是,如果在for each循环的过程中调用集合的remove()方法,就会导致循环出错,
因为循环过程中list.size()的大小变化了,就导致了错误。 所以,如果想在循环语句中删除集合中的某个元素,
就要用迭代器iterator的remove()方法,因为它的remove()方法不仅会删除元素,还会维护一个标志,
用来记录目前是不是可删除状态,这就涉及到源码了,想考虑了可以看下这个异常报错,链接如下:
( -->点击这个     http://blog.csdn.net/qq_27093465/article/details/52033629)
例如,你不能连续两次调用它的remove()方法,调用之前至少有一次next()方法的调用。  
forEach就是为了让用iterator循环访问的形式简单,写起来更方便。当然功能不太全,所以但如有删除操作,还是要用它原来的形式。
使用for循环与使用迭代器iterator的对比
效率上的各有优势
采用ArrayList对随机访问比较快,而for循环中的get()方法,采用的即是随机访问的方法,因此在ArrayList里,for循环较快
采用LinkedList则是顺序访问比较快,iterator中的next()方法,采用的即是顺序访问的方法,因此在LinkedList里,使用iterator较快
从数据结构角度分析,for循环适合访问顺序结构,可以根据下标快速获取指定元素.而Iterator 
适合访问链式结构,因为迭代器是通过next()和Pre()来定位的.可以访问没有顺序的集合. 
而使用 Iterator 的好处在于可以使用相同方式去遍历集合中元素,而不用考虑集合类的内部实现(只要它实现了 java.lang.Iterable 接口),
如果使用 Iterator 来遍历集合中元素,一旦不再使用 List 转而使用 Set 来组织数据,
那遍历元素的代码不用做任何修改,如果使用 for 来遍历,
那所有遍历此集合的算法都得做相应调整,
因为List有序,Set无序,结构不同,
他们的访问算法也不一样

可以了解下 继承list的几个类之间的差别,链接如下:
点击打开链接查看几个list之间的差别

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值