Java循环结构到底还干了些什么事情?求大神解释解释,这个问题困扰我很久了!

思想永无止境 2014-05-22 05:50:46
Java 特别奇葩的问题,请将代码拷贝至main方法运行:
程序一:
int[] a = new int[2000];

long timeMillis1 = System.currentTimeMillis();
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
// if (a[j] < a[i]) ;
}
}
System.out.println("第一次循环一共用时:" + (System.currentTimeMillis() - timeMillis1));

long timeMillis2 = System.currentTimeMillis();
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
// if (a[j] < a[i]) ;
}
}
System.out.println("第二次循环一共用时:" + (System.currentTimeMillis() - timeMillis2));

long timeMillis3 = System.currentTimeMillis();
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
// if (a[j] < a[i]) ;
}
}
System.out.println("第三次循环一共用时:" + (System.currentTimeMillis() - timeMillis3));

执行多次打印结果为:
第一次循环一共用时:3
第二次循环一共用时:2
第三次循环一共用时:2

第一次循环一共用时:3
第二次循环一共用时:3
第三次循环一共用时:2

第一次循环一共用时:2
第二次循环一共用时:2
第三次循环一共用时:2

第一次循环一共用时:3
第二次循环一共用时:2
第三次循环一共用时:3

将数组a的长度改为5000时执行多次打印结果为:
第一次循环一共用时:15
第二次循环一共用时:11
第三次循环一共用时:12

第一次循环一共用时:12
第二次循环一共用时:12
第三次循环一共用时:12

第一次循环一共用时:13
第二次循环一共用时:12
第三次循环一共用时:12

第一次循环一共用时:13
第二次循环一共用时:12
第三次循环一共用时:14

将数组a的长度改为10000时执行多次打印结果为:
第一次循环一共用时:49
第二次循环一共用时:46
第三次循环一共用时:46

第一次循环一共用时:49
第二次循环一共用时:46
第三次循环一共用时:48

第一次循环一共用时:47
第二次循环一共用时:46
第三次循环一共用时:47

第一次循环一共用时:50
第二次循环一共用时:49
第三次循环一共用时:46

将数组a的长度改为50000时执行多次打印结果为:
第一次循环一共用时:1154
第二次循环一共用时:1174
第三次循环一共用时:1150

第一次循环一共用时:1160
第二次循环一共用时:1156
第三次循环一共用时:1148

第一次循环一共用时:1152
第二次循环一共用时:1150
第三次循环一共用时:1149

第一次循环一共用时:1156
第二次循环一共用时:1163
第三次循环一共用时:1169

结论:大多数情况第一次会多一点,但都是随机不确定的
问题一:为什么第一次一般会多几毫秒?
问题二:为什么是大多数时候多几毫秒而不是每次都多几毫秒?

去掉循环内的注释,即执行循环内被注释的if (a[j] < a[i]) ;
执行多次打印结果为:
第一次循环一共用时:13
第二次循环一共用时:8
第三次循环一共用时:8

第一次循环一共用时:14
第二次循环一共用时:11
第三次循环一共用时:8

第一次循环一共用时:12
第二次循环一共用时:7
第三次循环一共用时:7

第一次循环一共用时:11
第二次循环一共用时:7
第三次循环一共用时:8

将数组a的长度改为5000时执行多次打印结果为:
第一次循环一共用时:70
第二次循环一共用时:47
第三次循环一共用时:47

第一次循环一共用时:68
第二次循环一共用时:47
第三次循环一共用时:46

第一次循环一共用时:69
第二次循环一共用时:46
第三次循环一共用时:47

第一次循环一共用时:68
第二次循环一共用时:47
第三次循环一共用时:47

将数组a的长度改为10000时执行多次打印结果为:
第一次循环一共用时:254
第二次循环一共用时:187
第三次循环一共用时:186

第一次循环一共用时:249
第二次循环一共用时:187
第三次循环一共用时:186

第一次循环一共用时:253
第二次循环一共用时:185
第三次循环一共用时:187

第一次循环一共用时:252
第二次循环一共用时:186
第三次循环一共用时:185

将数组a的长度改为50000时执行多次打印结果为:
第一次循环一共用时:6160
第二次循环一共用时:4632
第三次循环一共用时:4697

第一次循环一共用时:6178
第二次循环一共用时:4620
第三次循环一共用时:4633

第一次循环一共用时:6127
第二次循环一共用时:4591
第三次循环一共用时:4670

第一次循环一共用时:6194
第二次循环一共用时:4701
第三次循环一共用时:4632

结论一:第一次每次都多很多毫秒
结论二:随着数组长度越来越大,第一次与第二三次数比值越来越小从3:2降到4:3

问题一:为什么if (a[j] < a[i]) ;这句代码对结果的影响那么大?第一次回多那么多秒?
问题二:将这个两层循环改成单层循环的话,就一点区别都没有了,为什么
问题三:将这个两层循环改成单层循环的话并且将数组的长度改为100000以上,第一次又会多几毫秒,为什么?


程序二:
排序算法说明:理论上我的冒泡排序要比普通冒泡排序快大约1/3到1之间
int[] a = new int[1000];
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
}
}

random(a);
long time1 = System.currentTimeMillis();
for (int i = 0; i < a.length; i++) {
for (int j = a.length - 1; j > i; j--) {
int p = j - 1;
if (a[j] < a[p]) {
int temp = a[j];
a[j] = a[p];
a[p] = temp;
}
}
}
println(a);
System.out.println("我的冒泡排序一共用时:" + (System.currentTimeMillis() - time1));

random(a);
long time2 = System.currentTimeMillis();
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length - 1; j++) {
int p = j + 1;
if (a[j] > a[p]) {
int temp = a[j];
a[j] = a[p];
a[p] = temp;
}
}
}
println(a);
System.out.println("普通冒泡排序一共用时:" + (System.currentTimeMillis() - time2));

执行多次打印结果为:
我的冒泡排序一共用时:2
普通冒泡排序一共用时:4

我的冒泡排序一共用时:1
普通冒泡排序一共用时:3

我的冒泡排序一共用时:2
普通冒泡排序一共用时:3

我的冒泡排序一共用时:1
普通冒泡排序一共用时:4

将数组a的长度改为2000时执行多次打印结果为:
我的冒泡排序一共用时:6
普通冒泡排序一共用时:15

我的冒泡排序一共用时:7
普通冒泡排序一共用时:14

我的冒泡排序一共用时:6
普通冒泡排序一共用时:16

我的冒泡排序一共用时:7
普通冒泡排序一共用时:15

结论:这些结果符合我的预期结果,也就是说我的冒泡排序要比普通排序快大约1/3到1之间

我将前面5行代码改成:
int[] a = new int[1000];
//for (int i = 0; i < a.length; i++) {
//for (int j = 0; j < a.length; j++) {
//}
//}

也就是说我将两层空循环都注释掉的时候多次执行打印结果为:
我的冒泡排序一共用时:4
普通冒泡排序一共用时:4

我的冒泡排序一共用时:4
普通冒泡排序一共用时:3

我的冒泡排序一共用时:3
普通冒泡排序一共用时:3

我的冒泡排序一共用时:4
普通冒泡排序一共用时:2

结论:我的冒泡排序用时比普通排序用时要长
问题一:明明我的排序比较次数要少,为什么不加上前面那个空循环就反而比普通冒泡排序还要慢一点呢?

我将前面5行代码改成:
int[] a = new int[1000];
for (int i = 0; i < a.length; i++) {
//for (int j = 0; j < a.length; j++) {
//}
}

也就是说我将第二层循环注释掉的时候多次执行打印结果为:
我的冒泡排序一共用时:4
普通冒泡排序一共用时:3

我的冒泡排序一共用时:4
普通冒泡排序一共用时:2

我的冒泡排序一共用时:3
普通冒泡排序一共用时:3

我的冒泡排序一共用时:4
普通冒泡排序一共用时:4

结论:注释里面的一个循环与全部注释两个循环没有差别
问题一:既然两个空循环能影响排序用时的结果,那么为什么一个空循环就不能影响排序用时的结果呢?


问题二:此加不加if (a[j] < a[i]) ;这句代码都对结果没有任何影响,为什么?


程序二运行需要的代码:
public static Random random = new Random();

public static void random(int[] a) {
for (int i = 0; i < a.length; i++) {
a[i] = random.nextInt(a.length);
}
}

public static void println(int[] a) {
// for (int i = 0; i < a.length; i++) {
// System.out.print(a[i] + "\t");
// }
// System.out.println();
}
...全文
233 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
思想永无止境 2014-05-29
  • 打赏
  • 举报
回复
都不知道你是在解答我的哪个提问。。。
七神之光 2014-05-23
  • 打赏
  • 举报
回复
int[] a = new int[2000]; long timeMillis1 = System.currentTimeMillis(); 还有 不是你这样写 程序就会这样执行 有指令重排序 计时本身就不准确
七神之光 2014-05-23
  • 打赏
  • 举报
回复
太长了 首先 空循环 编译器会直接优化掉 不会执行的。
思想永无止境 2014-05-23
  • 打赏
  • 举报
回复
你都不看又何必问什么呢?
sunbo624 2014-05-23
  • 打赏
  • 举报
回复
写了一堆 你到底想问什么 没人爱看那么长的测试用例

67,512

社区成员

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

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