day7 7 Java數組中的一些注意事項

7、java數組裏的注意事項

7.1 數組的簡介

數組(array)是一種最簡單的複合數據類型,它是有序數據的集合,數組中的每個元素具有相同的數據類型,可以用一個統一的數組名和不同的下標來確定數組中唯一的元素。根據數組的維度,可以將其分爲一維數組二維數組多維數組等。

在計算機語言中數組是非常重要的集合類型,大部分計算機語言中數組具有如下三個基本特性:

  • 一致性:數組只能保存相同數據類型元素,元素的數據類型可以是任何相同的數據類型。
  • 有序性:數組中的元素是有序的,通過下標訪問。
  • 不可變性:數組一旦初始化,則長度(數組中元素的個數)不可變。

總的來說,數組具有以下特點:

  1. 數組可以是一維數組、二維數組或多維數組。
  2. 數值數組元素的默認值爲 0,而引用元素的默認值爲 null。
  3. 數組的索引從 0 開始,如果數組有 n 個元素,那麼數組的索引是從 0 到(n-1)。
  4. 數組元素可以是任何類型,包括數組類型。
  5. 數組類型是從抽象基類 Array 派生的引用類型。
請注意,Java 數組的工作原理與C++不同

7.2 注意事項

7.2.1 java數組的定義及初始化形式

1.一維數組(3種)

1)先聲明再分配空間再初始化

int []score;//聲明
score = new int[2];//分配空間
score[0] = 1;//賦值
score[1] = 2; 

聲明的同時分配空間再初始化

int []score = new int[2];
score[0]=1;
score[1]=2; 

以上兩種其實可以說是同一種。

2)聲明的同時分配空間、初始化

int []score = new int[]{1,2};//(方括號裏面不能有數字)
//錯誤寫法 int[]score = new int[2]{1,2};

3)聲明的同時初始化

int []score = {1,2};

例子

package Arraydata;

public class Notice_Demo {
    public static void main(String[]args){
        int []score ;
        score = new int[2];
        score[0]=1;
        score[1]=2;
        System.out.println("形式1:"+score[0]+" "+score[1]);

        int []score1 = new int[2];
        score1[0]=1;
        score1[1]=2;
        System.out.println("形式2:"+score1[0]+" "+score1[1]);

        int []score2= new int[]{1,2};
        System.out.println("形式3:"+score2[0]+" "+score2[1]);

        int []score3 = {1,2};
        System.out.println("形式4:"+score3[0]+" "+score3[1]);
    }
}

在這裏插入圖片描述

2.二維數組(3種)

int[][] temp = new int[][]{1,2,3,,值 n};    // 在定義時初始化
int[][] temp = new int[size1][size2];    // 給定空間,在賦值
int[][] temp = new int[size][];    // 數組第二維長度爲空,可變化,進而得到不規則數組

3.多維數組(含不規則數組)

想要提高數組的維數,只要在聲明數組時將索引與中括號再加一組即可,所以三維數組的聲明爲 int score[][][],而四維數組爲 int score[][][][],以此類推。
通常也將二維數組看作是多維數組。

public static void main(String[] args) {
    String[][][] namelist = { { { "張陽", "李風", "陳飛" }, { "樂樂", "飛飛", "小曼" } },
            { { "Jack", "Kimi" }, { "Lucy", "Lily", "Rose" } }, { { "徐璐璐", "陳海" }, { "李麗麗", "陳海清" } } };
    for (int i = 0; i < namelist.length; i++) {
        for (int j = 0; j < namelist[i].length; j++) {
            for (int k = 0; k < namelist[i][j].length; k++) {
                System.out.println("namelist[" + i + "][" + j + "][" + k + "]=" + namelist[i][j][k]);
            }
        }
    }
}

建議使用的初始化形式是:

type [][][] temp = {1,值2,值3};//注意這裏的值1,值2等是更低一級維度的數組(長度是否相等區別爲規則與不規則)。類似於python多維數組列表的形式

7.2.2 規則的數組與不規則的數組

規則的 4×3 二維數組有 12 個元素,而不規則數組就不一定了。如下代碼靜態初始化了一個不規則數組。

int intArray[][] = {{1,2}, {11}, {21,22,23}, {31,32,33}};

注意!!!

Java 實際上沒有多維數組,只有一維數組。
多維數組被解釋爲是數組的數組,所以因此會衍生出一種不規則數組。

7.2.3 使用 for-each來簡化遍歷數組(樣例 迷宮小遊戲)

package Arraydata;
import java.util.Scanner;
public class Array_demo {
    /**
     *  步驟分析:
     *             1.打印地圖  ---- 二維數組的遍歷
     *     初始座標 array[1][1]
     *     結束座標 array[1][9]
     *             2.如何讓0走起來
     *     通過修改 橫縱座標 讓'P'走起來
     *     如何碰到牆 '#' 不移動
     *     可以先把要走的位置元素 取出來判斷一下 是不是牆
     *     是牆就不動 不是牆再進行移動
     *     3.循環輸入(循環的停止條件 結束座標位置 從' '變成'0')
     *       使用while循環比較方便
     */
    public static void main(String[] args) {
        // 有8個一維數組 每個一維數組中有10個元素
        char[][] array = {
                //y   0   1   2   3   4   5   6   7   8   9
                    {'#','#','#','#','#','#','#','#','#','#'},//0 ----- x
                    {'#','P',' ',' ',' ',' ','#','#',' ',' '},//1
                    {'#','#',' ','#','#','#','#','#',' ','#'},//2
                    {'#',' ',' ',' ',' ','#','#','#',' ','#'},//3
                    {'#',' ','#','#',' ','#',' ',' ',' ','#'},//4
                    {'#',' ','#','#',' ','#',' ','#','#','#'},//5
                    {'#',' ',' ',' ',' ',' ',' ','#','#','#'},//6
                    {'#','#','#','#','#','#','#','#','#','#'},//7
        };
        // 打印地圖
        printMap(array);
        // 聲明要用的變量 起始
        int x = 1;
        int y = 1;
        // 結束
        int ex = 1;
        int ey = 9;
        Scanner scanner = new Scanner(System.in);
        // 提示輸入 w a s d
        while (array[ex][ey] != 'P') {
            System.out.println("請輸入w a s d進行移動");
            // 接收輸入的值
            String string = scanner.nextLine();
            // 判斷往哪裏移動
            switch (string) {
                case "w": case "W":
                    if (array[x - 1][y] != '#') {
                        // 把原來的改空格
                        array[x][y] = ' ';
                        // 向左移動
                        x = x - 1;
                        array[x][y] = 'P';
                    }
                    break;
                case "a": case"A":
                    if (array[x][y - 1] != '#') {
                        // 把原來的改空格
                        array[x][y] = ' ';
                        // 向左移動
                        y = y  - 1;
                        array[x][y] = 'P';
                    }
                    break;
                case "s": case"S":
                    if (array[x + 1][y] != '#') {
                        // 把原來的改空格
                        array[x][y] = ' ';
                        // 向左移動
                        x = x + 1;
                        array[x][y] = 'P';
                    }
                    break;
                case "d": case"D":
                    // 判斷是不是牆
                    if (array[x][y + 1] != '#') {
                        // 把原來的改空格
                        array[x][y] = ' ';
                        // 向左移動
                        y = y  + 1;
                        array[x][y] = 'P';
                    }
                    break;
                default:
                    break;
            }
            // 修改完畢後 再打印一遍地圖
            printMap(array);
        }
        System.out.println("恭喜通關!");
    }

    // 打印地圖的方法
    public static void printMap(char[][] array) {
        System.out.print(" ");
        for(int i=0;i<10;i++){
            System.out.print(i+"");
        }
        System.out.println();
        int j=0;
        for (char[] chars : array) {
            System.out.print(j+"");
            for (char aChar : chars) {
                System.out.print(aChar);
            }
            System.out.println();
            j++;
        }
    }
}

在這裏插入圖片描述
我們在打印地圖的函數裏面使用了for-each循環遍歷數組。

7.3 Array工具類

Arrays 類是一個工具類,其中包含了數組操作的很多方法。這個 Arrays 類裏均爲 static 修飾的方法(static 修飾的方法可以直接通過類名調用),可以直接通過 Arrays.xxx(xxx) 的形式調用方法。

1int binarySearch(type[] a, type key)

使用二分法查詢 key 元素值在 a 數組中出現的索引,如果 a 數組不包含 key 元素值,則返回負數。調用該方法時要求數組中元素己經按升序排列,這樣才能得到正確結果。

2int binarySearch(type[] a, int fromIndex, int toIndex, type key)

這個方法與前一個方法類似,但它只搜索 a 數組中 fromIndex 到 toIndex 索引的元素。調用該方法時要求數組中元素己經按升序排列,這樣才能得到正確結果。

3)type[] copyOf(type[] original, int length)

這個方法將會把 original 數組複製成一個新數組,其中 length 是新數組的長度。如果 length 小於 original 數組的長度,則新數組就是原數組的前面 length 個元素,如果 length 大於 original 數組的長度,則新數組的前面元索就是原數組的所有元素,後面補充 0(數值類型)、false(布爾類型)或者 null(引用類型)。

4)type[] copyOfRange(type[] original, int from, int to)

這個方法與前面方法相似,但這個方法只複製 original 數組的 from 索引到 to 索引的元素。

5)boolean equals(type[] a, type[] a2)

如果 a 數組和 a2 數組的長度相等,而且 a 數組和 a2 數組的數組元素也一一相同,該方法將返回 true。

6void fill(type[] a, type val)

該方法將會把 a 數組的所有元素都賦值爲 val。

7void fill(type[] a, int fromIndex, int toIndex, type val)

該方法與前一個方法的作用相同,區別只是該方法僅僅將 a 數組的 fromIndex 到 toIndex 索引的數組元素賦值爲 val。

8void sort(type[] a)

該方法對 a 數組的數組元素進行排序。

9void sort(type[] a, int fromIndex, int toIndex)

該方法與前一個方法相似,區別是該方法僅僅對 fromIndex 到 toIndex 索引的元素進行排序。

10)String toString(type[] a)

該方法將一個數組轉換成一個字符串。該方法按順序把多個數組元素連綴在一起,多個數組元素使用英文逗號,和空格隔開。

下面程序示範了 Arrays 類的用法。

public class ArraysTest {
    public static void main(String[] args) {
        // 定義一個a數組
        int[] a = new int[] { 3, 4, 5, 6 };
        // 定義一個a2數組
        int[] a2 = new int[] { 3, 4, 5, 6 };
        // a數組和a2數組的長度相等,毎個元素依次相等,將輸出true
        System.out.println("a數組和a2數組是否相等:" + Arrays.equals(a, a2));
        // 通過複製a數組,生成一個新的b數組
        int[] b = Arrays.copyOf(a, 6);
        System.out.println("a數組和b數組是否相等:" + Arrays.equals(a, b));
        // 輸出b數組的元素,將輸出[3, 4, 5, 6, 0, 0]
        System.out.println("b 數組的元素爲:" + Arrays.toString(b));
        // 將b數組的第3個元素(包括)到第5個元素(不包括)賦值爲1
        Arrays.fill(b, 2, 4, 1);
        // 輸出b數組的元素,將輸出[3, 4, 1, 1, 0, 0]
        System.out.println("b 數組的元素爲:" + Arrays.toString(b));
        // 對b數組進行排序
        Arrays.sort(b);
        // 輸出b數組的元素.將輸出[0,0,1,1,3,4]
        System.out.println("b數組的元素爲:" + Arrays.toString(b));
    }
}

Arrays 類處於 java.util 包下,爲了在程序中使用 Arrays 類,必須在程序中導入 java.util.Arrays 類。

注意在 System 類裏的static void arraycopy(Object src, int srePos, Object dest, int dcstPos, int length)方法,該方法可以將 src 數組裏的元素值賦給 dest 數組的元素,其中 srcPos 指定從 src 數組的第幾個元素開始賦值,length 參數指定將 src 數組的多少個元素值賦給 dest 數組的元素。

Java 8 增強了 Arrays 類的功能,爲 Arrays 類增加了一些工具方法,這些工具方法可以充分利用多 CPU 並行的能力來提高設值、排序的性能。下面是 Java 8 爲 Arrays 類增加的工具方法。

提示:由於計算機硬件的飛速發展,目前幾乎所有家用 PC 都是 4 核、8 核的 CPU,而服務器的 CPU 則具有更好的性能,因此 Java 8 與時俱進地增加了併發支持,併發支持可以充分利用硬件設備來提高程序的運行性能。

1)oid parallelPrefix(xxx[] array, XxxBinaryOperator op)

該方法使用 op 參數指定的計算公式計算得到的結果作爲新的元素。op 計算公式包括 left、right 兩個形參,其中 left 代表數組中前一個索引處的元素,right 代表數組中當前索引處的元素,當計算第一個新數組元素時,left 的值默認爲 1。

2void parallelPrefix(xxx[] array, int fromIndex, int toIndex, XxxBinaryOperator op)

該方法與上一個方法相似,區別是該方法僅重新計算 fromIndex 到 toIndex 索引的元素。

3void setAll(xxx[] array, IntToXxxFunction generator)

該方法使用指定的生成器(generator)爲所有數組元素設置值,該生成器控制數組元素的值的生成算法。

4void parallelSetAll(xxx[] array, IntToXxxFunction generator)

該方法的功能與上一個方法相同,只是該方法增加了並行能力,可以利用多 CPU 並行來提高性能。

5void parallelSort(xxx[] a)

該方法的功能與 Arrays 類以前就有的 sort() 方法相似,只是該方法增加了並行能力,可以利用多 CPU 並行來提高性能。

6void parallelSort(xxx[] a,int fromIndex, int toIndex)

該方法與上一個方法相似,區別是該方法僅對 fromIndex 到 toIndex 索引的元素進行排序。

7)Spliterator.OfXxx spliterator(xxx[] array)

將該數組的所有元素轉換成對應的 Spliterator 對象。

8)Spliterator.OfXxx spliterator(xxx[] array, int startInclusive, int endExclusive)

該方法與上一個方法相似,區別是該方法僅轉換 startInclusive 到 endExclusive 索引的元素。

9)XxxStream stream(xxx[] array)

該方法將數組轉換爲 Stream,Stream 是 Java 8 新增的流式編程的 API。

10)XxxStream stream(xxx[] array, int startInclusive, int endExclusive)

該方法與上一個方法相似,區別是該方法僅將 fromIndex 到 toIndex 索引的元索轉換爲 Stream。

上面方法列表中,所有以 parallel 開頭的方法都表示該方法可利用 CPU 並行的能力來提高性能。上面方法中的 xxx 代表不同的數據類型,比如處理 int[] 型數組時應將 xxx 換成 int,處理 long[] 型數組時應將 XXX 換成 long。

下面程序示範了 Java 8 爲 Arrays 類新增的方法。

public class ArraysTest2 {
    public static void main(String[] args) {
        int[] arr1 = new int[] { 3, 4, 25, 16, 30, 18 };
        // 對數組arr1進行併發排序
        Arrays.parallelSort(arr1);
        System.out.println(Arrays.toString(arr1));
        int[] arr2 = new int[] { 13, -4, 25, 16, 30, 18 };
        Arrays.parallelPrefix(arr2, new IntBinaryOperator() {
            // left 代表數組中前一個索引處的元素,計算第一個元素時,left爲1
            // right代表數組中當前索引處的元素
            public int applyAsInt(int left, int right) {
                return left * right;
            }
        });
        System.out.println(Arrays.toString(arr2));
        int[] arr3 = new int[5];
        Arrays.parallelSetAll(arr3, new IntUnaryOperator() {
            // operand代表正在計算的元素索引
            public int applyAsInt(int operand) {
                return operand * 5;
            }
        });
        System.out.println(Arrays.toString(arr3));
    }
}

上面程序中第一行粗體字代碼調用了 parallelSort() 方法對數組執行排序,該方法的功能與傳統 sort() 方法大致相似,只是在多 CPU 機器上會有更好的性能。

第二段粗體字代碼使用的計算公式爲 left * right,其中 left 代表數組中當前一個索引處的元素,right 代表數組中當前索引處的元素。程序使用的數組爲:
{3, -4 , 25, 16, 30, 18)

計算新的數組元素的方式爲:
{13=3, 3-4—12, -1225=-300, -30016=—48000, -4800030=—144000, -14400018=-2592000}

因此將會得到如下新的數組元素:
{3, -12, -300, -4800, -144000, -2592000)

第三段粗體字代碼使用 operand * 5 公式來設置數組元素,該公式中 operand 代表正在計算的數組元素的索引。因此第三段粗體字代碼計算得到的數組爲:
{0, 5, 10, 15, 20}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章