Java數組(Array)最全匯總(中篇)
前言
本章是關于Java數組的最全匯總,本篇為匯總中篇,主要講了二維數組和不規(guī)則的數組的相關內容。
數組是最常見的一種數據結構,它是相同類型的用一個標識符封裝到一起的基本類型數據序列或者對象序列。
數組使用一個統(tǒng)一的數組名和不同的下標來唯一確定數組中的元素。
實質上,數組是一個簡單的線性序列,因此訪問速度很快。
本章將詳細介紹 Java 中數組的創(chuàng)建、初始化和處理方法,如獲取數組長度、查找數組元素和數組排序等。
本章學習要點
- 掌握一維數組的創(chuàng)建方法
- 掌握一維數組的初始化方法
- 熟練掌握一維數組的應用
- 掌握二維數組的創(chuàng)建
- 掌握二維數組的初始化
- 熟練掌握二維數組元素的訪問方式
- 掌握數組的復制方法
- 掌握搜索數組元素的方法
- 掌握對數組的排序算法
Java二維數組詳解
為了方便組織各種信息,計算機常將信息以表的形式進行組織,然后再以行和列的形式呈現出來。
二維數組的結構決定了其能非常方便地表示計算機中的表,以第一個下標表示元素所在的行,第二個下標表示元素所在的列。
下面簡單了解一下二維數組,包括數組的聲明和初始化。
創(chuàng)建二維數組
在 Java 中二維數組被看作數組的數組,即二維數組為一個特殊的一維數組,其每個元素又是一個一維數組。
Java 并不直接支持二維數組,但是允許定義數組元素是一維數組的一維數組,以達到同樣的效果。聲明二維數組的語法如下:
type arrayName[][]; // 數據類型 數組名[][];
或
type[][] arrayName; // 數據類型[][] 數組名;
其中,type 表示二維數組的類型,arrayName 表示數組名稱,第一個中括號表示行,第二個中括號表示列。
下面分別聲明 int 類型和 char 類型的數組,代碼如下:
int[][] age;char[][] sex;
初始化二維數組
二維數組可以初始化,和一維數組一樣,可以通過 3 種方式來指定元素的初始值。這 3 種方式的語法如下:
type[][] arrayName = new type[][]{值 1,值 2,值 3,…,值 n}; // 在定義時初始化
type[][] arrayName = new type[size1][size2]; // 給定空間,在賦值
type[][] arrayName = new type[size][]; // 數組第二維長度為空,可變化例 1
使用第一種方式聲明 int 類型的二維數組,然后初始化該二維數組。代碼如下:
int[][] temp = new int[][]{{1,2},{3,4}};上述代碼創(chuàng)建了一個二行二列的二維數組 temp,并對數組中的元素進行了初始化。圖 1 所示為該數組的內存結構。

圖1 二維數組內存結構
使用第二種方式聲明 int 類型的二維數組,然后初始化該二維數組。代碼如下:
int[][] temp = new int[2][2];
使用第三種方式聲明 int 類型的二維數組,并且初始化數組。代碼如下:
int[][] temp = new int[2][];
獲取單個元素
在上部分使用的前 2 種方式創(chuàng)建并初始化了一個二行二列的 int 類型數組 temp。
當需要獲取二維數組中元素的值時,也可以使用下標來表示。語法如下:
arrayName[i-1][j-1];
其中,arrayName 表示數組名稱,i 表示數組的行數,j 表示數組的列數。
例如,要獲取第二行第二列元素的值,應該使用 temp[1][1]來表示。
這是由于數組的下標起始值為 0,因此行和列的下標需要減 1。
例 2
通過下標獲取 class_score 數組中第二行第二列元素的值與第四行第一列元素的值。代碼如下:
public static void main(String[] args) {
double[][] class_score = {{10.0,99,99},{100,98,97},{100,100,99.5},{99.5,99,98.5}};
System.out.println("第二行第二列元素的值:"+class_score[1][1]);
System.out.println("第四行第一列元素的值:"+class_score[3][0]);
}執(zhí)行上述代碼,輸出結果如下:
第二行第二列元素的值:98.0 第四行第一列元素的值:99.5
獲取全部元素
在一維數組中直接使用數組的 length 屬性獲取數組元素的個數。
而在二維數組中,直接使用 length 屬性獲取的是數組的行數,在指定的索引后加上 length(如 array[0].length)表示的是該行擁有多少個元素,即列數。
如果要獲取二維數組中的全部元素,最簡單、最常用的辦法就是使用 for 語句。
在一維數組全部輸出時,我們使用一層 for 循環(huán),而二維數組要想全部輸出,則使用嵌套 for 循環(huán)(2 層 for 循環(huán))。
例 3
使用 for 循環(huán)語句遍歷 double 類型的 class_score 數組的元素,并輸出每一行每一列元素的值。代碼如下:
public static void main(String[] args) {
double[][] class_score = { { 100, 99, 99 }, { 100, 98, 97 }, { 100, 100, 99.5 }, { 99.5, 99, 98.5 } };
for (int i = 0; i < class_score.length; i++) { // 遍歷行
for (int j = 0; j < class_score[i].length; j++) {
System.out.println("class_score[" + i + "][" + j + "]=" + class_score[i][j]);
}
}
}上述代碼使用嵌套 for 循環(huán)語句輸出二維數組。
在輸出二維數組時,第一個 for 循環(huán)語句表示以行進行循環(huán),第二個 for 循環(huán)語句表示以列進行循環(huán),這樣就實現了獲取二維數組中每個元素的值的功能。
執(zhí)行上述代碼,輸出結果如下所示。
class_score[0][0]=100.0 class_score[0][1]=99.0 class_score[0][2]=99.0 class_score[1][0]=100.0 class_score[1][1]=98.0 class_score[1][2]=97.0 class_score[2][0]=100.0 class_score[2][1]=100.0 class_score[2][2]=99.5 class_score[3][0]=99.5 class_score[3][1]=99.0 class_score[3][2]=98.5
例 4
假設有一個矩陣為 5 行 5 列,該矩陣是由程序隨機產生的 10 以內數字排列而成。下面使用二維數組來創(chuàng)建該矩陣,代碼如下:
public class Test11 {
public static void main(String[] args) {
// 創(chuàng)建一個二維矩陣
int[][] matrix = new int[5][5];
// 隨機分配值
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
matrix[i][j] = (int) (Math.random() * 10);
}
}
System.out.println("下面是程序生成的矩陣\n");
// 遍歷二維矩陣并輸出
for (int k = 0; k < matrix.length; k++) {
for (int g = 0; g < matrix[k].length; g++) {
System.out.print(matrix[k][g] + "");
}
System.out.println();
}
}
}在該程序中,首先定義了一個二維數組,然后使用兩個嵌套的 for 循環(huán)向二維數組中的每個元素賦值。
其中,Math.random() 方法返回的是一個 double 類型的數值,數值為 0.6、0.9 等,因此乘以 10 之后為 10 以內的整數。
最后又使用了兩個嵌套的 for 循環(huán)遍歷二維數組,輸出二維數組中的值,從而產生矩陣。
運行該程序的結果如下所示。
下面是程序生成的矩陣 78148 69230 43823 75663 05688
for each 循環(huán)語句不能自動處理二維數組的每一個元素。
它是按照行, 也就是一維數組處理的。要想訪問二維教組 a 的所有元素, 需要使用兩個嵌套的循環(huán), 如下所示:
for (double[] row : a) {
for (double value : row) {
......
}
}把【例2】修改為使用 for each 循環(huán)語句輸出,代碼如下所示:
public static void main(String[] args) {
double[][] class_score = { { 100, 99, 99 }, { 100, 98, 97 }, { 100, 100, 99.5 }, { 99.5, 99, 98.5 } };
for (double[] row : class_score) {
for (double value : row) {
System.out.println(value);
}
}
}輸出結果為:
100.0
99.0
99.0
100.0
98.0
97.0
100.0
100.0
99.5
99.5
99.0
98.5
提示:要想快速地打印一個二維數組的數據元素列表,可以調用:
System.out.println(Arrays.deepToString(arrayName));
代碼如下:
System.out.println(Arrays.deepToString(class_score));
輸出格式為:
[[100.0, 99.0, 99.0], [100.0, 98.0, 97.0], [100.0, 100.0, 99.5], [99.5, 99.0, 98.5]]
獲取整行元素
除了獲取單個元素和全部元素之外,還可以單獨獲取二維數組的某一行中所有元素的值,或者二維數組中某一列元素的值。
獲取指定行的元素時,需要將行數固定,然后只遍歷該行中的全部列即可。
例 5
編寫一個案例,接收用戶在控制臺輸入的行數,然后獲取該行中所有元素的值。代碼如下:
public static void main(String[] args) {
double[][] class_score = { { 100, 99, 99 }, { 100, 98, 97 }, { 100, 100, 99.5 }, { 99.5, 99, 98.5 } };
Scanner scan = new Scanner(System.in);
System.out.println("當前數組只有" + class_score.length + "行,您想查看第幾行的元素?請輸入:");
int number = scan.nextInt();
for (int j = 0; j < class_score[number - 1].length; j++) {
System.out.println("第" + number + "行的第[" + j + "]個元素的值是:" + class_score[number - 1][j]);
}
}執(zhí)行上述代碼進行測試,輸出結果如下所示。
當前數組只有4行,您想查看第幾行的元素?請輸入: 3 第3行的第[0]個元素的值是:100.0 第3行的第[1]個元素的值是:100.0 第3行的第[2]個元素的值是:99.5
獲取整列元素
獲取指定列的元素與獲取指定行的元素相似,保持列不變,遍歷每一行的該列即可。
例 6
編寫一個案例,接收用戶在控制臺中輸入的列數,然后獲取二維數組中所有行中該列的值。代碼如下:
public static void main(String[] args) {
double[][] class_score = { { 100, 99, 99 }, { 100, 98, 97 }, { 100, 100, 99.5 }, { 99.5, 99, 98.5 } };
Scanner scan = new Scanner(System.in);
System.out.println("您要獲取哪一列的值?請輸入:");
int number = scan.nextInt();
for (int i = 0; i < class_score.length; i++) {
System.out.println("第 " + (i + 1) + " 行的第[" + number + "]個元素的值是" + class_score[i][number]);
}
}執(zhí)行上述代碼進行測試,如下所示。
您要獲取哪一列的值?請輸入: 2 第 1 行的第[2]個元素的值是99.0 第 2 行的第[2]個元素的值是97.0 第 3 行的第[2]個元素的值是99.5 第 4 行的第[2]個元素的值是98.5
Java不規(guī)則數組
通過前面的學習我們知道 Java 實際上沒有多維數組,只有一維數組。
多維數組被解釋為是數組的數組,所以因此會衍生出一種不規(guī)則數組。
規(guī)則的 4×3 二維數組有 12 個元素,而不規(guī)則數組就不一定了。
如下代碼靜態(tài)初始化了一個不規(guī)則數組。
int intArray[][] = {{1,2}, {11}, {21,22,23}, {31,32,33}};
高維數組(二維以及二維以上的數組稱為高維數組)是 4 個元素,但是低維數組元素個數不同,如圖 1 所示,其中第 1 個數組有兩個元素,第 2 個數組有 1 個元素,第 3 個數組有 3 個元素,第 4 個數組有 3 個元素。這就是不規(guī)則數組。

圖 1 不規(guī)則數組
動態(tài)初始化不規(guī)則數組比較麻煩,不能使用 new int[4][3] 語句,而是先初始化高維數組,然后再分別逐個初始化低維數組。代碼如下:
int intArray[][] = new int[4][]; //先初始化高維數組為4 // 逐一初始化低維數組 intArray[0] = new int[2]; intArray[1] = new int[1]; intArray[2] = new int[3]; intArray[3] = new int[3];
從上述代碼初始化數組完成之后,不是有 12 個元素而是 9 個元素,它們的下標索引如圖 2 所示,可見其中下標 [0][2]、[1][1] 和 [1][2] 是不存在的,如果試圖訪問它們則會拋出下標越界異常。

圖 2 不規(guī)則數組訪問
提示:下標越界異常(ArrayIndexOutOfBoundsException)是試圖訪問不存在的下標時引發(fā)的。
例如一個一維 array 數組如果有 10 個元素,那么表達式 array[10] 就會發(fā)生下標越界異常,這是因為數組下標是從 0 開始的,最后一個元素下標是數組長度減 1,所以 array[10] 訪問的元素是不存在的。
下面介紹一個不規(guī)則數組的示例:
import java.util.Arrays;
public class HelloWorld {
public static void main(String[] args) {
int intArray[][] = new int[4][]; // 先初始化高維數組為4
// 逐一初始化低維數組
intArray[0] = new int[2];
intArray[1] = new int[1];
intArray[2] = new int[3];
intArray[3] = new int[3];
// for循環(huán)遍歷
for (int i = 0; i < intArray.length; i++) {
for (int j = 0; j < intArray[i].length; j++) {
intArray[i][j] = i + j;
}
}
// for-each循環(huán)遍歷
for (int[] row : intArray) {
for (int column : row) {
System.out.print(column);
// 在元素之間添加制表符,
System.out.print('\t');
}
// 一行元素打印完成后換行
System.out.println();
}
System.out.println(intArray[0][2]); // 發(fā)生運行期錯誤
}
}不規(guī)則數組訪問和遍歷可以使用 for 和 for-each 循環(huán),但要注意下標越界異常發(fā)生。
上述代碼第 18 行和第 19 行采用 for-each 循環(huán)遍歷不規(guī)則數組,其中代碼第 18 行 for-each 循環(huán)取出的數據是 int 數組,所以 row 類型是 int[]。代碼第 19 行 for-each 循環(huán)取出的數據是 int 數據,所以 column 的類型 int。
另外,注意代碼第 27 行試圖訪問 intArray[0][2]元素,由于 [0][2] 不存在所以會發(fā)生下標越界異常。
Java數組也是一種數據類型
Java 的數組要求所有的數組元素具有相同的數據類型。
因此,在一個數組中,數組元素的類型是唯一的,即一個數組里只能存儲一種數據類型的數據,而不能存儲多種數據類型的數據。
因為 Java 語言是面向對象的語言,而類與類之間可以支持繼承關系(從已有的類中派生出新的類,新的類能吸收已有類的數據屬性和行為),這樣可能產生一個數組里可以存放多種數據類型的假象。
例如有一個水果數組,要求每個數組元素都是水果,實際上數組元素既可以是蘋果,也可以是香蕉(蘋果、香蕉都繼承了水果,都是一種特殊的水果),但這個數組的數組元素的類型還是唯一的,只能是水果類型。
一旦數組的初始化完成,數組在內存中所占的空間將被固定下來,因此數組的長度將不可改變。
即使把某個數組元素的數據清空,但它所占的空間依然被保留,依然屬于該數組,數組的長度依然不變。
Java 的數組既可以存儲基本類型的數據,也可以存儲引用類型的數據,只要所有的數組元素具有相同的類型即可。
值得指出的是,數組也是一種數據類型,它本身是一種引用類型。
例如 int 是一個基本類型,但 int[](這是定義數組的一種方式)就是一種引用類型了。
int[] 是一種類型嗎?怎么使用這種類型呢?
沒錯,int[] 就是一種數據類型,與 int 類型、String 類型相似,一樣可以使用該類型來定義變量,也可以使用該類型進行類型轉換等。
使用 int[] 類型來定義變量、進行類型轉換時與使用其他普通類型沒有任何區(qū)別。
int[] 類型是一種引用類型,創(chuàng)建 int[] 類型的對象也就是創(chuàng)建數組,需要使用創(chuàng)建數組的語法。
Java中到底有沒有多維數組(長篇神文)?
Java 中沒有多維數組的概念,從數組底層的運行機制上來看 Java 沒有多維數組,但是 Java 提供了支持多維數組的語法,可以實現多維數組的功能。
Java 語言里的數組類型是引用類型,因此數組變量其實是一個引用,這個引用指向真實的數組內存。數組元素的類型也可以是引用,如果數組元素的引用再次指向真實的數組內存,這種情形看上去很像多維數組。
定義數組類型的語法
type[] arrName;
是典型的一維數組的定義語法,其中 type 是數組元素的類型。
如果希望數組元素也是一個引用,而且是指向 int 數組的引用,則可以把 type 具體成 int[](前面已經指出,int[] 就是一種類型,int[] 類型的用法與普通類型并無任何區(qū)別),那么上面定義數組的語法就是
int[][] arrName
如果把 int 這個類型擴大到 Java 的所有類型(不包括數組類型),則出現了定義二維數組的語法:
type[][] arrName;
Java 語言采用上面的語法格式來定義二維數組,但它的實質還是一維數組,只是其數組元素也是引用,數組元素里保存的引用指向一維數組。
接著對這個“二維數組”執(zhí)行初始化,同樣可以把這個數組當成一維數組來初始化,把這個“二維數組”當成一個一維數組,其元素的類型是 type[] 類型,則可以采用如下語法進行初始化:
arrName = new type[length][]
上面的初始化語法相當于初始化了一個一維數組,這一維數組的長度是 length。
同樣,因為這個一維數組的數組元素是引用類型(數組類型)的,所以系統(tǒng)為每個數組元素都分配初始值:null。
這個二維數組實際上完全可以當成一維數組使用:使用
new type[length]
初始化一維數組后,相當于定義了 length 個 type 類型的變量。
類似的,使用
new type[length][]
初始化這個數組后,相當于定義了 length 個 type[] 類型的變量。
當然,這些 type[] 類型的變量都是數組類型,因此必須再次初始化這些數組。
下面程序示范了如何把二維數組當成一維數組處理。
public class TwoDimensionTest {
public static void main(String[] args) {
// 定義一個二維數組
int[][] a; // 把a當成一維數組進行初始化,初始化a是一個長度為4的數組
// a數組的數組元素又是引用類型
a = new int[4][]; // 把a數組當成一維數組,遍歷a數組的每個數組元素
for (int i = 0, len = a.length; i < len; i++) {
System.out.println(a[i]); // 輸出 null null null null
} // 初始化a數組的第一個元素
a[0] = new int[2];
// 訪問a數組的第一個元素所指數組的第二個元素
a[0][1] = 6;
// a數組的第一個元素是一個一維數組,遍歷這個一維數組
for (int i = 0, len = a[0].length; i < len; i++) {
System.out.println(a[0][i]); // 輸出 0 6
}
}
}
上面程序中粗體字代碼部分把 a 這個二維數組當成一維數組處理,只是每個數組元素都是 null,所以看到輸出結果都是 null。
下面結合示意圖來說明這個程序的執(zhí)行過程。
程序中代碼
int[][] a;
將在棧內存中定義一個引用變量,這個變量并未指向任何有效的內存空間,此時的堆內存中還未為這行代碼分配任何存儲區(qū)。
程序中代碼
a = new int[4][];
對a 數組執(zhí)行初始化,這行代碼讓 a 變量指向一塊長度為 4 的數組內存,這個長度為 4 的數組里每個數組元素都是引用類型(數組類型),系統(tǒng)為這些數組元素分配默認的初始值:null。此時 a 數組在內存中的存儲示意圖如圖 1 所示。

圖 1 將二維數組當成一維數組初始化的存儲示意圖
從圖 1 來看,雖然聲明 a 是一個二維數組,但這里絲毫看不出它是一個二維數組的樣子,完全是一維數組的樣子。
這個一維數組的長度是 4,只是這 4 個數組元素都是引用類型,它們的默認值是 null。
所以程序中可以把 a 數組當成一維數組處理,依次遍歷 a 數組的每個元素,將看到每個數組元素的值都是 null。
由于 a 數組的元素必須是 int[] 數組,所以接下來的程序對 a[0] 元素執(zhí)行初始化,也就是讓圖 1 右邊堆內存中的第一個數組元素指向一個有效的數組內存,指向一個長度為 2 的 int 數組。
因為程序采用動態(tài)初始化 a[0] 數組,因此系統(tǒng)將為 a[0] 所引用數組的每個元素分配默認的初始值:0,然后程序顯式為 a[0] 數組的第二個元素賦值為 6。
此時在內存中的存儲示意圖如圖 2 所示。
![初始化a[0]后的存儲示意圖](http://img.jbzj.com/file_images/article/202301/2023011315140944.png)
圖 2 初始化a[0]后的存儲示意圖
圖 2 中灰色覆蓋的數組元素就是程序顯式指定的數組元素值。
TwoDimensionTest.java 接著迭代輸出 a[0] 數組的每個數組元素,將看到輸出 0 和 6。
是否可以讓圖 2 中灰色覆蓋的數組元素再次指向另一個數組?這樣不就可以擴展成三維數組,甚至擴展成更多維的數組嘛?
不能!至少在這個程序中不能。
因為 Java 是強類型語言,當定義 a 數組時,已經確定了 a 數組的數組元素是 int[] 類型,則 a[0] 數組的數組元素只能是 int 類型,所以灰色覆蓋的數組元素只能存儲 int 類型的變量。
對于其他弱類型語言,例如 JavaScript 和 Ruby 等,確實可以把一維數組無限擴展,擴展成二維數組、三維數組…,如果想在 Java 語言中實現這種可無限擴展的數組,則可以定義一個 Object[] 類型的數組,這個數組的元素是 Object 類型,因此可以再次指向一個 Object[] 類型的數組,這樣就可以從一維數組擴展到二維數組、三維數組…
從上面程序中可以看出,初始化多維數組時,可以只指定最左邊維的大?。划斎?,也可以一次指定每一維的大小。例如下面代碼:
// 同時初始化二維數組的兩個維數 int[][] b = new int[3][4];
上面代碼將定義一個 b 數組變量,這個數組變量指向一個長度為 3 的數組,這個數組的每個數組元素又是一個數組類型,它們各指向對應的長度為 4 的 int[] 數組,每個數組元素的值為 0。
這行代碼執(zhí)行后在內存中的存儲示意圖如圖 3 所示。

圖 3 同時初始化二維數組的兩個維數后的存儲示意圖
還可以使用靜態(tài)初始化方式來初始化二維數組。
使用靜態(tài)初始化方式來初始化二維數組時,二維數組的每個數組元素都是一維數組,因此必須指定多個一維數組作為二維數組的初始化值。如下代碼所示:
// 使用靜態(tài)初始化語法來初始化一個二維數組
String[][] str1 = new String[][]{new String[3], new String[]{“hello”}};
// 使用簡化的靜態(tài)初始化語法來初始化二維數組
String[][] str2 = {new String[3], new String [] {“hello”}};上面代碼執(zhí)行后內存中的存儲示意圖如圖 4 所示。

圖 4 采用靜態(tài)初始化語法初始化二維數組的存儲示意圖
通過上面講解可以得到一個結論:二維數組是一維數組,其數組元素是一維數組。三維數組也是一維數組,其數組元素是二維數組…… 從這個角度來看,Java 語言里沒有多維數組。
到此這篇關于Java數組(Array)最全匯總(中篇)的文章就介紹到這了,其他兩個部分的內容(上、下篇)請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Java數組(Array)最全匯總(上篇)
- Java之數組在指定位置插入元素實現
- Java自定義一個變長數組的思路與代碼
- Java中如何將?int[]?數組轉換為?ArrayList(list)
- Java中將 int[] 數組 轉換為 List分享
- java如何將int數組轉化為Integer數組
- 淺談Java當作數組的幾個應用場景
- 計算Java數組長度函數的方法以及代碼分析
- Java C++題解leetcode915分割數組示例
- Java?從json提取數組并轉換為list的操作方法
- Java數據結構之稀疏數組的實現與應用
- Java?C++題解leetcode1441用棧操作構建數組示例
- Java postgresql數組字段類型處理方法詳解
- Java中數組的常見操作合集
- 關于Java?SE數組的深入理解
- Java二維數組與稀疏數組相互轉換實現詳解
- Java數組隊列及環(huán)形數組隊列超詳細講解
- Java數組(Array)最全匯總(下篇)
相關文章
Java之next()、nextLine()區(qū)別及問題解決
這篇文章主要介紹了Java之next()、nextLine()區(qū)別及問題解決,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-08-08
基于eclipse-temurin鏡像部署spring boot應用的實現示例
本文提供了基于eclipse-temurin鏡像部署Spring Boot應用的詳細實現示例,通過使用Docker鏡像,可以輕松地創(chuàng)建和管理Spring Boot應用程序的容器化環(huán)境,感興趣的可以了解一下2023-08-08

