2015-05-11 72 views
0

我知道結果是相同的,但第一個循環比第二個循環快。這是爲什麼?二維數組迭代方法比另一種方法更快

int[][] values = new int[10][20]; 

int sum = 0; 
int count = 0; 
for (int j = 0; j < 20; j++) { 

    for (int i = 0; i < 10; i++) { 
     count++; 
     values[i][j] = count; 

     sum += values[i][j]; 
    } 

} 
System.out.println(sum); 

int[][] values = new int[10][20]; 

int sum = 0; 
int count = 0; 
for (int i = 0; i < 10; i++) { 

    for (int j = 0; j < 20; j++) { 
     count++; 
     values[i][j] = count; 

     sum += values[i][j]; 
    } 

} 
System.out.println(sum); 
+0

你有什麼疑問?你想知道什麼? – Rahul

+0

@joshstrike的答案是正確的! – paykoob

+0

我試過你的代碼,都給出了相同的輸出:20100.所以沒有什麼是錯的 – smttsp

回答

0

因爲忘記切換在值[i] [j]時,推動它們到該陣列。

+3

切換我和j會給一個ArrayIndexOutOfBoundsException。 – Eran

+0

values [i] [j]在第二個版本中可能是正確的,並且在第一個版本中是錯誤的,但無論如何它可能需要首先測試或定義,這就是爲什麼他的兩段代碼生成兩個不同的代碼款項。 – joshstrike

+0

它們都產生相同的總和 - 20100. – Eran

3

這是一個loop interchange

雖然我不能確切地觀察到相同的結果你的機器(我的是與英特爾i7-4770K相當仡,代碼是在非常簡單的類,我使用的堆棧溢出的問題),一般來說,這種循環具有更高性能的傾向。

它更高性能的主要原因是由於它迭代的元素的局部性。遍歷連續內存比非連續內存更有效。

讓我們考慮一個典型的陣列:

int[] anArray = new int[5]; 

在內存中,Java將保留*的五個連續的塊都能夠保持一個int。

int[5] -> [][][][][] 

*:或者至少試試。

對於一個二維數組,Java將執行相同的操作,而不是像內存中的網格那樣出現(與C一樣),您將有一個指向數組的數組。

int[2][3] -> [ ] [ ] 
       | | 
       v v 
      [ ] [ ] 
      [ ] [ ] 
      [ ] [ ] 

在存儲器佈局方面,第二層的陣列(即,那些長度20的)有可能更接近在存儲器相互之間比它們與一線陣列(即,那些長度10)。迭代連續內存比非連續內存效率更高,這就是爲什麼你注意到速度提高的原因。

+0

是的,這就解釋了爲什麼第二種循環方式應該比第一種循環更快。但是OP聲稱與此相反。 – kirelagin