当前位置: 代码迷 >> Java面试 >> Java面试题之二维数组性能有关问题
  详细解决方案

Java面试题之二维数组性能有关问题

热度:4844   发布时间:2013-02-25 21:25:57.0
Java面试题之二维数组性能问题

前不久去面试了一家公司,面试题是这样的:

?

一个二维数组赋值,有两种循环方法,问是第一种循环效率高,还是第二种循环效率高,代码如下:

?

int a[][] = new int[M][N];int b[][] = new int [M][N];int c[][] = new int[M][N];for(int i=0;i<M;i++){      for(int j=0;j<N;j++)      {           c[i][j] = a[i][j]*b[i][j];      }}for(int j=0;j<N;j++){    for(int i=0;i<M;i++)    {         c[i][j] = a[i][j]*b[i][j];    }}

?

当时认为一般编程都是用第一种方法遍历,没有推荐用第二种方法的,应该第一种效率要高。

回来测试了一下,当M=1000,N=2000时,第一种循环用时15秒,第二种循环用时63秒,明显第一种效率要高,可是究竟是什么原因呢。

?

?

用javap分析第一种for循环

public static void main(java.lang.String[]);  Code:   Stack=5, Locals=6, Args_size=1   0:   sipush  1000   3:   sipush  2000   6:   multianewarray  #16,  2; //class "[[I"   10:  astore_1   11:  sipush  1000   14:  sipush  2000   17:  multianewarray  #16,  2; //class "[[I"   21:  astore_2   22:  sipush  1000   25:  sipush  2000   28:  multianewarray  #16,  2; //class "[[I"   32:  astore_3   33:  iconst_0   34:  istore  4   36:  goto    81   39:  iconst_0   40:  istore  5   42:  goto    70   45:  aload_3   //将c的地址压栈   46:  iload   4   //将i的值压栈   48:  aaload     //将上两个值出栈,并将c[i]的值压栈   49:  iload   5   //将j的值压栈   51:  aload_1   52:  iload   4   54:  aaload   55:  iload   5   57:  iaload   58:  aload_2   59:  iload   4   61:  aaload   62:  iload   5   64:  iaload   65:  imul   66:  iastore   67:  iinc    5, 1   70:  iload   5   72:  sipush  2000   75:  if_icmplt       45   78:  iinc    4, 1   81:  iload   4   83:  sipush  1000   86:  if_icmplt       39   89:  return  LineNumberTable:   line 18: 0   line 19: 11   line 20: 22   line 23: 33   line 25: 39   line 27: 45   line 25: 67   line 23: 78   line 43: 89  LocalVariableTable:   Start  Length  Slot  Name   Signature   0      90      0    args       [Ljava/lang/String;   11      79      1    a       [[I   22      68      2    b       [[I   33      57      3    c       [[I   36      53      4    i       I   42      36      5    j       I?

第二种for循环

public static void main(java.lang.String[]); Code: Stack=5, Locals=6, Args_size=1 0: sipush 1000 3: sipush 2000 6: multianewarray #16, 2; //class "[[I" 10: astore_1 11: sipush 1000 14: sipush 2000 17: multianewarray #16, 2; //class "[[I" 21: astore_2 22: sipush 1000 25: sipush 2000 28: multianewarray #16, 2; //class "[[I" 32: astore_3 33: iconst_0 34: istore 4 36: goto 81 39: iconst_0 40: istore 5 42: goto 70 45: aload_3 46: iload 5 48: aaload 49: iload 4 51: aload_1 52: iload 5 54: aaload 55: iload 4 57: iaload 58: aload_2 59: iload 5 61: aaload 62: iload 4 64: iaload 65: imul 66: iastore 67: iinc 5, 1 70: iload 5 72: sipush 1000 75: if_icmplt 45 78: iinc 4, 1 81: iload 4 83: sipush 2000 86: if_icmplt 39 89: return LineNumberTable: line 18: 0 line 19: 11 line 20: 22 line 34: 33 line 36: 39 line 38: 45 line 36: 67 line 34: 78 line 43: 89 LocalVariableTable: Start Length Slot Name Signature 0 90 0 args [Ljava/lang/String; 11 79 1 a [[I 22 68 2 b [[I 33 57 3 c [[I 36 53 4 j I 42 36 5 i I

?

?

由此可以看出,每次都是从一维数组开始根据内存地址查找,找到一维数组的地址后再找二维数组的地址,然后将此地址的实际值压栈,类似链表结构。第二种for循环因为首先要将数组a的地址入栈,然后遍历第一维数组,然后用aaload将数组当前下标存放的地址值入栈,由于第一维数组不同,所以需要频繁出栈入栈第一维数组,时间就被浪费在这里。

  相关解决方案