读书人

阿里巴巴2014笔考试题速来围观!

发布时间: 2013-10-01 12:15:56 作者: rapoo

阿里巴巴2014笔试题,速来围观!!!
问下面哪个方法计算速度更快



public class FFFtest {
public static void main(String[] args) {
int[] a=new int[1000];
int[] b=new int[10000000];
long start = System.currentTimeMillis();
//method 1
for(int i=0;i<1000;i++){
for(int j=0;j<10000000;j++){
a[i]++;
}
}
long end = System.currentTimeMillis();
System.out.println(end-start);

start=System.currentTimeMillis();
//method 2
for(int i=0 ;i<10000000;i++){
for(int j=0;j<1000;j++){
b[i]++;
}
}
end = System.currentTimeMillis();
System.out.println(end-start);


}
}

输出:
25616
21736

结果表示,第二中更快一些,求解释!!! 阿里巴巴 java
[解决办法]
测试1:将赋值语句注释
 public static void main(String[] args) {
int[] a=new int[1000];
int[] b=new int[10000000];
long start = System.currentTimeMillis();
//method 1
for(int i=0;i<1000;i++){
for(int j=0;j<10000000;j++){
// a[i]++;
}
}
long end = System.currentTimeMillis();
System.out.print(end-start+"\t");

start=System.currentTimeMillis();
//method 2
for(int i=0 ;i<10000000;i++){
for(int j=0;j<1000;j++){
// b[i]++;
}
}
end = System.currentTimeMillis();
System.out.println(end-start);

}

测试结果:
3704 4095
36253860
36093877
36094001


测试2:恢复赋值(同楼主代码)
测试结果:
2361622096
2304821986
2416422495
2353222175

结果分析:
1、通过测试1(仅循环切换耗时)可以证明6楼的所说,第一段代码从内层循环切到外层的次数为 1000次;第二段代码从内层循环切到外层的次数为10000000次,所以切换多的耗时多

2、通过测试2看到加上赋值后第一段代码明显耗时明显增加,两段代码赋值次数都一样,但是第一段代码每一个数组元素都是从1-10000000赋值,存大赋值大数据

所以我觉得整体来说大赋值大数据耗时会比较多
[解决办法]
这题的理性认识应该是第一个比较快。
因为a[i]和b[i]都是一个内存查找的动作,而a[i]只查找了1000次,b[i]却查找了10000000次。a[i]更多地击中了CPU的缓存(快),而b[i]更多地进行了内存查找(慢)。

于是乎这就是一个micro benchmark的问题了。Java的micro benchmark是很难的,也没有什么绝对公平的方法。难点在于JVM的JIT。

对于进行micro benchmark的方法,首先要进行预热,其次要进行统计。
预热的概念是让JVM先行运行该方法若干次(关键词:compile threshold),使其JIT对方法进行优化和编译。
统计的意思是运行多次测试,取平均值、中值、标准差等数据进行综合比较。
另外要注意的一点是,绝对不能在同一个程序里面测试两种方法。要编译测试两个方法的不同版本分别进行测试,否则会有干扰。

以下是我的测试方法:这个测试里面我没有用统计方法,因为结果已经很明显了:方法一比方法二快了2.5倍左右

package test;

public class Test {

static int[] a = new int[100];
static int[] b = new int[100000];

public static void main(final String[] args) throws Exception {

// warm up
for (int i = 0; i < 5000; i++)
method2();

long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++)
method2();
long end = System.currentTimeMillis();
System.out.println(end - start);
}

static void method1() {
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100000; j++) {
a[i]++;
}


}
}

static void method2() {
for (int i = 0; i < 100000; i++) {
for (int j = 0; j < 100; j++) {
b[i]++;
}
}
}
}



这是方法二的测试代码,你想要测方法一,只需要把main里面的method2改成method1

读书人网 >J2SE开发

热点推荐