多維數組的遍歷性能

數組是Java中的一種容器對象,它擁有多個單一類型的值。當數組被建立的時候數組長度就已經肯定了。在建立以後,其長度是固定的。下面是一個長度爲10的數組:html

public class ArrayDemo {
    private int arraySize=10;
    public int[] arrayOfIntegers = new int[arraySize];
}

上面的代碼是一維數組的例子。換句話說,數組長度只能在一個方向上增加。不少時候咱們須要數組在多個維度上增加。這種數組咱們稱之爲多維數組。爲簡單起見,咱們將它稱爲2維數組。當咱們須要一個矩陣或者X-Y座標系的時候,二維數組是很是有用的。下面就是一個二維數組的例子:java

public class TheProblemOf2DArray {
    private static final int ARR_SIZE=10;
    public static void main(String[] args) {
        int arr[][]=new int[ARR_SIZE][ARR_SIZE];
    }
}

想象一下,一個二維數組看起來就像一個X-Y座標系的矩陣。數組

然而,可能讓Java開發者們感到驚訝的是,Java實際上並無二維數組。性能

在一個真正的數組中,全部的元素在內存中都存放在連續的內存塊中,可是在Java的二維數組並非這樣。Java中全部一維數組中的元素佔據了相鄰的內存位置,所以是一個真正的數組。this

在Java中,當咱們定義:code

int singleElement // 表示一個int變量
int[] singleDArray // 表示一個int變量數組(一維)
int[][] twoDArray // 表示一個int變量數組的數組(二維)htm

這意味着,在上面的例子中,二維數組是一個數組的引用,其每個元素都是另外一個int數組的引用。對象

這張圖片清楚地解釋了這個概念。圖片

因爲二維數組分散在存儲器中,因此對性能有一些影響。爲了分析這種差別,我寫了一個簡單的Java程序,顯示遍歷順序的重要性內存

/**
 * 二維數組的問題
 * 
 * 咱們在初始化一個任意大小的2維數組。(爲簡化分析咱們使用二維方陣)咱們將用兩種不一樣方式迭代同一個數組,分析結果 兩種迭代方式的性能差距很大
 * 
 * @author mohit
 * 
 */
public class TheProblemOf2DArray {
    // 數組大小:數組越大,性能差距越明顯
    private static final int ARR_SIZE = 9999;

    public static void main(String[] args) {
        // 新數組
        int arr[][] = new int[ARR_SIZE][ARR_SIZE];
        long currTime = System.currentTimeMillis();
        colMajor(arr);
        System.out.println("Total time in colMajor : "
                + (System.currentTimeMillis() - currTime) + " ms");
        // 新數組,與arr徹底相同
        int arr1[][] = new int[ARR_SIZE][ARR_SIZE];
        currTime = System.currentTimeMillis();
        rowMajor(arr1); // this is the only difference in above
        System.out.println("Total time in col : "
                + (System.currentTimeMillis() - currTime) + " ms");
    }

    /**
     * 下面的代碼按列優先遍歷數組 即在掃描下一列以前先掃描完本列
     * 
     */
    private static void colMajor(int arr[][]) {
        for (int i = 0; i < ARR_SIZE; i++) {
            for (int j = 0; j < ARR_SIZE; j++) {
                // See this, we are traversing j first and then i
                arr[i][j] = i + j;
            }
        }
    }

    /**
     * 若是咱們轉換內外循環 程序就以行優先順序遍歷數組 即在掃描下一行以前先掃描完本行
     * 這意味着咱們訪問數組時每次都在訪問不一樣的列(所以也在訪問不一樣的頁) 代碼微小的改變將致使這個程序花費更多的時間完成遍歷
     */
    private static void rowMajor(int arr[][]) {
        for (int i = 0; i < ARR_SIZE; i++) {
            for (int j = 0; j < ARR_SIZE; j++) {
                /*
                 * 看這個,咱們先遍歷j,而後遍歷i,可是對於訪問元素來講 它們在更遠的位置,因此須要花費的更多
                 */
                arr[j][i] = i + j;
            }
        }
    }
}

下面是運行結果:

Total time in colMajor : 133 ms
Total time in col : 2036 ms

能夠看出性能差距仍是很大的,因此在操做二維數組的時候按順序操做。

相關文章
相關標籤/搜索