Java 循环性能分析

最近coding的时候对循环的性能很好奇,面对多种循环方式,迭代器、for循环、forEach循环、lambda的forEach循环。

如果单论代码美观,个人偏向于lambda的forEach循环和forEach循环。但是这样唐突的选择很有可能造成性能的下降。

后面本人就分析了一下各个循环之间的效率:

一、ArrayList

size=100000
for:8
forEach:12
Iterator:11
lambda:115
size=1000

for:4
forEach:1
Iterator:0
lambda:98

size=10000

for:6
forEach:2
Iterator:1
lambda:107
 

    可以看出,当size很大(10万)时候for循环的性能最高,当size不是很大的时候Iterator和forEach效率就高。ArrayList的底层是数组形式,这不得不从它们的取数逻辑入手,如下:

(1)foreach循环和iterator迭代器:

         foreach的底层是通过iterator循环,通过调用iterator.next(),查看ArrayList对于iterator中next方法的实现可知其最终是通过数组下标获取元素。

(2)for循环

         for语句快里直接通过下标取数

(3)lambda的forEach循环

         开启多线程并发处理

       从如上遍历、取数逻辑中可得出,for在数据量小时,由于多了index++、index

 

对于如何选择,总结了如下几点,可参考

1.如果是需要对下标进行处理操作对则选择for循环;

2.对于ArrayList,从代码简洁讲优先考虑foreach,也不用去考虑下标越界对问题;

3.对于实效性要求不高的,如I/O操作,可考虑lambda的forEach循环。

 

二、LinkedList

size=100000

for:18
forEach:10
Iterator:9
lambda:108

 

size=10000

for:9
forEach:3
Iterator:2
lambda:104

 

size=1000

for:4
forEach:1
Iterator:0
lambda:114

       此时Iterator性能最佳,由于LinkedList的数据结构为链表结构,其中每个节点都记录了前驱和后继结点(头、尾除外)。通过下标的方式获得值都会在链中检查一遍,直到得到我们想要的下标节点为止。而Iterator和forEach则是始终循环子节点,直到尾节点为止。考虑到代码简洁,建议使用forEach。

 

三、HashMap

size=100000

forEach:17

Iterator:13

lambda:125

 

size=10000

forEach:4

Iterator:3

lambda:102

 

size=1000

forEach:1

Iterator:1

lambda:11

   这里我测试了三组数据(都是取entrySet为例),不难发现Iterator循环始终效率方面要占优,这里简单的提下HashMap的放值和取值原理。

   HashMap是一个散列桶,由数组和链表组成。每次put操作都会得到key的hash值,然后根据得到的hash值选择map数组对应的下标存入bucket(存入键对象和值对象)。而get操作时是根据键对象的hash值找map数组中对应的bucket,然后得到对应的值(当存在hash碰撞时,会以链表的形式加在相同hash值的后面,每次get的时候调用keys.equals()得到该键与之对应的值)。

   在之前的List对比中已经说明forEach循环底层也是由Iterator实现,而lambda的forEach循环是充分利用cup实现多线程的迭代。所以不难得出HashMap遍历Iterator效率更高一点,但是基于代码简洁性考虑也可采用forEach循环方式。

 

你可能感兴趣的:(java,遍历循环,性能分析,数据结构)