关于JAVA for循环效率的问题

梦鱼的鹿 2012-07-14 07:30:02
今天在C#里面看到:
之前一直认为
for (int i = 0, h = arr.Count; i < h; i++)

for (int i = 0; i < arr.Count; i++)
两种写法,在C#里应该是差不多的,今天突然有人问,就写了个程序测试了一下,结果出乎我的意料
如果arr是List<T>,前者的效率比后者高大约一倍,如果arr是string[],两者效率基本差不多

原帖子地址:http://topic.csdn.net/u/20120706/16/CEB33682-FF71-402C-9FE9-580F5ECFDFC1.html

我写的代码测试:int tnum = 1000000; // 添加或查找的次数
int outnum = 10; // 外层循环次数
ArrayList<String> arr = new ArrayList<String>();
for (int i = 0; i < tnum; i++) {
arr.add(Integer.toString(i));
}
String[] arr2 = new String[tnum];
for(int j=0;j<outnum;j++)
{
Long time = System.currentTimeMillis();
String msg;
msg = "Number ";
for (int i = 0, h = arr.size(); i < h; i++)
{
}
time = System.currentTimeMillis()-time;
System.out.println(msg+"耗时:"+time);

msg = ".Count ";
time = System.currentTimeMillis();
for (int i = 0; i < arr.size(); i++)
{
}
time = System.currentTimeMillis()-time;
System.out.println(msg+"耗时:"+time);

msg = "Length ";
time = System.currentTimeMillis();
for (int i = 0; i < arr2.length; i++)
{
}
time = System.currentTimeMillis()-time;
System.out.println(msg+"耗时:"+time);
}
我发现时间都差不多啊,难道是因为ArrayList的原因?还是JAVA这个用的时间本来就是一样的?
...全文
713 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
qybao 2012-07-15
  • 打赏
  • 举报
回复
LZ这样比较是很难看出来的,还是查看伪代码指令比较好理解
import java.util.*;
public class jp {
public static void main(String[] args) throws Throwable {
List<String> list = new ArrayList<String>();
for (int i=0, j=list.size(); i<j; i++); //list.size()只调用一次
for (int i=0; i<list.size(); i++); //list.size()每次都调用
}
}


javac jp.java //编译
javap -c jp //查看伪代码指令

E:\Test>javap -c jp
Compiled from "jp.java"
public class jp {
public jp();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":
()V
4: return

public static void main(java.lang.String[]) throws java.lang.Throwable;
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init
>":()V
7: astore_1
8: iconst_0
9: istore_2
10: aload_1
11: invokeinterface #4, 1 // InterfaceMethod java/util/List.si
ze:()I
16: istore_3
17: iload_2
18: iload_3
19: if_icmpge 28
22: iinc 2, 1
25: goto 17

28: iconst_0
29: istore_2
30: iload_2
31: aload_1
32: invokeinterface #4, 1 // InterfaceMethod java/util/List.si
ze:()I
37: if_icmpge 46
40: iinc 2, 1
43: goto 30

46: return
}

红色部分是第一种循环情况
8: iconst_0把0入栈
9: isrote_2把0出栈并赋给2号索引变量i,即i=0操作,1号索引变量是list,即前面的astore_1把ArrayList对象赋给1号索引变量
10: aload_1把1号索引变量入栈,即list入栈
11: invokeinterface把list出栈并调用其size方法,把结果入栈
16: istore_3把size方法的结果出栈并赋给3号索引变量j,即j=list.size()操作
17: iload_2
18: iload_3 把2,3号索引变量入栈
19: if_icmpge 28 比较入栈的两个数据,前者大于等于后者则跳转到28行指令,即不满足i<j跳转
22: iinc 2, 1 2号索引变量i自增1
25: goto 17 跳转到17行指令,即for重新开始循环


蓝色部分是第二种情况(循环体)
28:iconst_0 0入栈
29:istore_2 0出栈并赋给i
30:iload_2 i入栈
31:aload_1 list入栈
32:invokeinterface list出栈并调用size方法,把结果入栈
37: if_icmpge 46 比较入栈的两个数据,前者大于等于后者则跳转到46行指令,即不满足i<list.size
40: iinc 2, 1 2号索引变量i自增1
43: goto 30 跳转到30行指令,即for重新开始循环


比较可以看出,第一种情况,list.size只需要执行一次,第二种则每次循环都要执行
  • 打赏
  • 举报
回复
好的不是一点点~~
梦鱼的鹿 2012-07-15
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

LZ这样比较是很难看出来的,还是查看伪代码指令比较好理解
Java code
import java.util.*;
public class jp {
public static void main(String[] args) throws Throwable {
List<String> list = new ArrayList<String>();
……
[/Quote]
就是说还是
for (int i=0, j=list.size(); i<j; i++); //list.size()只调用一次
好点咯?
zuxianghuang 2012-07-14
  • 打赏
  • 举报
回复
,重复调用的问题
haiercs 2012-07-14
  • 打赏
  • 举报
回复
我就看不懂这玩意到底有啥含义,能证明什么呢,你项目中会有这样的情况发生吗

67,543

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧