上篇在foreach中有引入一個數組的概念,數組是最為常見的一種數據結構,是相同類型的、用一個標識符封裝到一起的基本類型數據序列或對象序列。
數組是具有相同數據類型的一組數據的集合,根據維數不同可以分為一維數組、二維數組和多維數組。大家可以將一維看作直線,二維看作平面、三維看成立體空間。
一、一維數組
1. 創建一維數組
數組作為對象允許使用new關鍵字進行內存分配。在使用數組之前,必須首先定義數組變量所屬的類型,即聲明數組。
聲明數組有兩種形式,在之前的篇章中也有所提及,語法格式如下:
數組元素類型 數組名[];
數據元素類型[] 數組名;
程序員在編寫代碼時習慣使用第二種方法,需要注意的聲明時是[]中不能添加任何數據。下面是一個聲明數組的例子,兩種聲明方式都正確,不同數據要聲明不同類型的數組:
int arr[]; // 聲明int型數組,數組中每個元素都是int型數值 String[] str; // 聲明String數組,數組中每個元素都是String數組
聲明數組后還不能訪問它的任何元素,要想真正使用數組還要為其分配內存空間,且分配內存空間時必須指明數組的長度。語法格式如下:
數組名 = new 數組元素類型[數組元素個數];
下面舉一個例子,為數組分配一個大小為5的內存空間:
arr = new int[5];
一維數組arr的存儲狀態如下圖:
arr[0] | arr[1] | arr[2] | arr[3] | arr[4] |
括號中的0、1、2、3、4表示數組的下標。需要注意的是,下標從0開始,到數組長度-1為止。
當然也可以直接聲明並分配內存,如下:
int[] week = new int[7];
上述代碼創建了一個一維數組week,並指定了數組長度為7。
還有一點需要注意的是,使用new關鍵字為數組分配內存時,數組中各個元素的初始化值都為0。比如上述代碼使用new關鍵字創建了長度為7的week數組,那么數組中的元素可以表示為[0, 0, 0, 0, 0, 0, 0],這就是一個一維數組,數組中的每一個元素都初始化為0。
2. 初始化一維數組
前面說的初始化是使用new關鍵字自動初始化,數組也可以與基本數據類型一樣由程序員進行初始化操作,可以分別初始化數組中的每個元素。
數組初始化的方式有兩種,下面用一個例子來說明:
int arr1[] = new int[]{1,2,3,4,5,6}; // 第一種 int arr2[] = {10,11,12,13,14}; // 第二種
數組初始化的方式是:把數據包括在大括號之內,中間用逗號分開數組中的元素的值,系統自動為數組分配一定的空間。上述第一種創建了6個元素的數組,其值依次為1、2、3、4、5、6,第二種創建了5個元素的數組,其值依次為10、11、12、13、14。
下面我們結合上篇的流程控制來舉一個一維數組數組的例子。
eg:求一維數組中各元素的和
1 public class SumNum { 2 3 public static void main(String[] args) { 4 int[] num = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 創建並初始化數組 5 int sum = 0; // 存儲累加和 6 7 for(int i=0; i<num.length; i++) { 8 if(i == num.length-1) { // 判斷下標是否是最后一個 9 System.out.print(num[i] + "="); // 輸出等號 10 } else { 11 System.out.print(num[i] + "+"); // 輸出加號 12 } 13 sum += num[i]; 14 } 15 16 System.out.print(sum); 17 } 18 19 }
其中,num是數組名,這個數組總長是10,但一般在編程中,可能會出現需要修改數組長度的時候,此時假設for循環中寫的是i<10,那么我們在修改代碼時可能會忽略這個地方導致出現意想不到的錯誤,所以我們在編寫代碼時,要習慣性使用數組名.length來獲取數組的長度,如上述代碼中的num.length其實就是10。而下一句中的num.length-1是因為數組下標是從0開始的,當我們獲取最后一個元素時,數組下標為總長減一,故num.length-1就是最后一個元素10的下標為9。最后的運行結果為:
二、多維數組
1. 二維數組
如果一維數組中的各個元素仍是一維數組,那么它就是一個二維數組。二維數組常用於表示表,表中的信息以行和列的形式組織,第一個下標代表元素所在的行,第二個下標代碼元素所在的列。或用線性代數的知識來說,二維數組就是一個矩陣,第一個下標代表矩陣的行,第二個下標代表矩陣的列。
二維數組的聲明也有兩種方式,語法格式如下:
數組元素類型 數組名[][];
數組元素類型[][] 數組名;
與一維數組一樣,如果聲明時沒有分配內存空間,同樣也要使用關鍵字new來分配內存。
二維數組可以看作由多個一維數組組成,在給二維數組分配內存時,可以為這些一維數組同時分配相同的內存。第一個中括號中的數組是一維數組的個數,第二個中括號中是一維數組的長度。
int arr = new int[2][4];
上述代碼就是一個典型的聲明一個二維數組arr並為其分配內存空間,分配后arr擁有兩個長度為4的一維數組,內存分配如下圖:
arr[0][0] | arr[0][1] | arr[0][2] | arr[0][3] |
arr[1][0] | arr[1][1] | arr[1][2] | arr[1][3] |
我們也可以為每一維單獨分配內存。如下:
int[][] a = new int[2][]; a[0] = new int[2]; a[1] = new int[3];
這樣我們就可以得到一個二維數組,第一個一維數組長度為2,第二個一維數組長度為3。
二維數組的初始化與一維數組類似,同樣可以使用大括號完成二維數組的初始化。如下:
int arr[][] = {{3,0},{5,7},{6,9}};
這就是一個arr[3][2]的數組,有三個一維數組,每個一維數組的長度都為2。但要明確下標是從開始的,比如arr[1][0]=5,指的是第二個一維數組的第一個元素為5。故我們也可以直接給arr[x][y]賦值,如給arr[1]的第二個元素賦值:
arr[1][1] = 50;
那么上述數組就變成了如下形式:
int arr[][] = {{3,0},{5,50},{6,9}};
2. 三維數組
對於三維數組,想必各位已經能推算出來了,一維用一個括號,二維用兩個括號,那么三維就用三個括號。
int arr[][][] = new int[][][]{ {{1,2,3},{4,5,6}}, {{7,8,9},{10,11,12}}, {{13,14,15},{16,17,18}} };
三、數組的基本操作
1. 遍歷數組
遍歷數組就是獲取數組中的每個元素,通常遍歷數組都是用for循環實現的。
遍歷一維數組只需用一個for循環即可實現,如下例:
int[] week = {1,2,3,4,5,6,7} for(int i=0; i<7; i++) { System.out.println(week[i]); }
還有另一種遍歷方法就是使用foreach語句,這個在上一篇最后已經提到了,這里就不再過多贅述了,直接上代碼:
for(int arr : week) { System.out.println(arr); }
遍歷二維數組比一維稍微麻煩一點,需使用雙層循環,如下例:
int a[][] = {{1,2},{3,4,5},{6,7,8,9}}; for(int i=0; i<a.length; i++) { for(int j=0; j<a[i].length; j++) { System.out.print(a[i][j] + " "); // 輸出 } System.out.println(); // 換行 }
需要注意的是,第一個for循環是遍歷行的,所以是長度是a.length,而第二個for循環是遍歷列的,長度是a[i].length。
再強調一次print和println的區別,print是輸出但不換行,println是輸出並換行,所以輸出結果如下:
2. 對數組進行排序
數組可以通過使用java.util包中的Arrays類來實現排序,sort()方法提供了許多重載形式,可對任意類型數組進行升序排序。語法格式為 Arrays.sort(object);
eg:創建一數組,排序后輸出。
1 public class Taxis { 2 3 public static void main(String[] args) { 4 int[] arr = new int[] {17, 21, 6, 59, 31, 13, 3}; 5 6 System.out.println("原始數組:"); 7 for(int i=0; i<arr.length; i++) { 8 System.out.print(arr[i] + " "); 9 } 10 11 Arrays.sort(arr); // 按字典順序排序 12 13 System.out.println("\n排序后的數組:"); 14 for(int i=0 ; i<arr.length; i++) { 15 System.out.print(arr[i] + " "); 16 } 17 } 18 19 }
Java語言中的String類型數組排序算法是根據字典編排順序排序的,因此數字排在字母前面,大寫字母排在小寫字母前面。運行結果如下:
3. 其它操作
數組還有許多操作,比如填充替換數組元素的fill方法、復制數組的copyOf方法等等,包括Arrays類也還提供了其它操作數組的方法,大家可以通過查閱資料或API來學習它們的使用方法。
還有一個很重要的知識點就是排序算法,上面已經出現了多重循環,那么就可以由此引出諸如冒泡排序、選擇排序等等的許多排序算法,如果以后有時間我可能會總結一下各類排序算法,常見的有冒泡、選擇、直接插入、快速、歸並、希爾、堆排序等等,這是學習編程語言必須掌握的知識點之一,網上也有許多資料,大家可自行查閱學習了解。