-
前言
for几乎是每个语言的基础语句,熟练的使用for是每个程序员所必备的,然而你真的懂得for循环的不凡麽? -
基础语句
for循环一般由4个表达式组成for(表达式1;表达式2;表达式3){ 表达式4; }
第一表达式 第二表达式 第三表达式 第四表达式 初始化变量的语句 条件判断语句 每次循环结束后执行语句 逻辑处理代码块 例:1-1
int[] array = {1,2,3}; for(int i = 0;i < array.length;i++){ System.out.println(array[i]); }
-
执行顺序
第一表达式→第二表达式→如果满足→第四表达式→第三表达式
第一表达式→第二表达式→如果不满足→结束也就是对应的:
初始化变量i→判断i是否小于array.length→如果满足→执行console.log(array[i]);→执行i++
初始化变量i→判断i是否小于array.length→如果不满足→结束 -
循环嵌套
在一个循环体语句中又包含另一个循环语句称为循环嵌套
在很多的业务场景中,单一的循环往往不能满足大多业务需求,大多时候我们都需要进行多层的循环嵌套。例:
注:这里为了方便写的是js的写法var array = [{ "id": 1, "names": [{ "uname": 1, "cname": 1 }, { "uname": 2, "cname": 2 }] }, { "id": 2, "names": [{ "uname": 1, "cname": 1 }, { "uname": 2, "cname": 2 }] }]
这样的数据格式,想要拿到每个uname的值则需要进行循环嵌套的写法:
for(var i = 0;i < array.length;i++){ var names= array[i].names; //第二个循环 for(var j= 0;j< names.length;j++){ console.log( names[j].uname;); } }
执行顺序:初始化变量i→判断i是否小于array.length→执行第四表达式→拿到names数组的值→遍历names数组→执行i++
遍历names数组又拆分为:
初始化变量j→判断j是否小于names.length→执行第四表达式→执行j++ -
解析优化
直接看下优化后的代码:1-2int[] array = {1,2,3}; for(int i = 0,length = array.length;i < length;i++){ System.out.println(array[i]); }
1-1为我们平时最为常见的for循环写法,我们可以看到在执行第二表达式的时候,每个循环都会去计算array.length的值,然后将array.length的值保存到栈内存中,最后才拿出i与存放到栈内存中的值进行比较,这样的话如果当循环的量级达到一定程度的时候,所产生的多余消耗是直观体现出来的。
1-2则在第一表达式的时候直接初始化了变量i和变量length,所以再后续的每个循环里面都无需再去计算length的值,直接比较i和length的大小,性能与1-1比自然得到提升。
证:
long startTime=System.nanoTime(); int[] array = new int[500000]; for(int i = 0,length = array.length;i < length;i++){ } long endTime=System.nanoTime(); System.out.println("程序运行时间: "+(endTime-startTime)+"ns"); //10101000ns
long startTime=System.nanoTime(); int[] array = new int[5000000]; for(int i = 0;i < array.length;i++){ } long endTime=System.nanoTime(); System.out.println("程序运行时间: "+(endTime-startTime)+"ns"); //12382600ns
这个需要足够多的次数与量级足够多的循环次数以及足够稳定的运行环境验证是否正确