Java多重數(shù)組使用及說明
概念
在 Java 中,“多重數(shù)組”通常指的是多維數(shù)組(Multidimensional Arrays),最常見的是二維數(shù)組(如矩陣),但也可以有三維、四維等。
多重數(shù)組概念
Java 的多重數(shù)組本質(zhì)上是 “數(shù)組的數(shù)組”(array of arrays),即:
- 一維數(shù)組:
int[] arr - 二維數(shù)組:
int[][] matrix→ 每個元素是一個int[] - 三維數(shù)組:
int[][][] cube→ 每個元素是一個int[][]
Java 的多維數(shù)組不要求每行長度相同(稱為“鋸齒數(shù)組”或“不規(guī)則數(shù)組”)。
聲明與初始化
1. 聲明
int[][] matrix; // 聲明一個二維整型數(shù)組 String[][][] data; // 三維字符串數(shù)組
2. 初始化方式
方式一:直接字面量初始化(推薦用于小數(shù)據(jù))
int[][] grid = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
方式二:指定大小(規(guī)則矩形)
int rows = 3, cols = 4; int[][] mat = new int[rows][cols]; // 3x4 的全 0 矩陣
方式三:鋸齒數(shù)組(Jagged Array)— 每行長度不同
int[][] jagged = new int[3][]; // 3 行,列數(shù)未定 jagged[0] = new int[2]; // 第0行有2列 jagged[1] = new int[5]; // 第1行有5列 jagged[2] = new int[1]; // 第2行有1列
注意:new int[3][4] 是規(guī)則數(shù)組;new int[3][] 是鋸齒數(shù)組(需手動初始化每行)。
訪問與修改元素
int value = matrix[i][j]; // 讀取第 i 行第 j 列 matrix[i][j] = 100; // 修改
邊界檢查:Java 會在運行時自動檢查下標是否越界(拋出 ArrayIndexOutOfBoundsException)。
遍歷多重數(shù)組
1. 普通 for 循環(huán)(知道行列數(shù))
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
matrix.length→ 行數(shù)matrix[i].length→ 第 i 行的列數(shù)(支持鋸齒數(shù)組?。?/li>
2. 增強 for 循環(huán)(for-each,簡潔安全)
for (int[] row : matrix) {
for (int val : row) {
System.out.print(val + " ");
}
System.out.println();
}
推薦:優(yōu)先使用 for-each,避免下標錯誤,尤其處理鋸齒數(shù)組時更安全。
內(nèi)存結(jié)構(gòu)(重要理解)
Java 的二維數(shù)組不是一塊連續(xù)內(nèi)存(不像 C/C++),而是:
- 一個一維數(shù)組,每個元素指向另一個一維數(shù)組
- 所以可以每行長度不同(鋸齒)
matrix → [ ref0, ref1, ref2 ]
↓ ↓ ↓
[1,2] [3,4,5] [6]
優(yōu)勢:靈活;劣勢:緩存局部性較差(相比連續(xù)內(nèi)存)
常見使用場景(面試高頻)
| 場景 | 示例 |
|---|---|
| 矩陣操作 | 旋轉(zhuǎn)矩陣、螺旋遍歷、對角線遍歷 |
| 動態(tài)規(guī)劃 | 二維 DP 表(如 LCS、編輯距離) |
| 圖的鄰接矩陣 | graph[i][j] == 1 表示 i→j 有邊 |
| 棋盤/地圖模擬 | 迷宮、島嶼數(shù)量、生命游戲 |
| 分組存儲 | 每行代表一類數(shù)據(jù) |
實用工具方法
1. 獲取行列數(shù)
int rows = matrix.length; int cols = matrix[0].length; // 注意:僅當至少有一行且非空時安全!
安全寫法(處理空數(shù)組):
if (matrix == null || matrix.length == 0) return; int rows = matrix.length; int cols = matrix[0].length; // 此時可安全訪問
2. 深拷貝二維數(shù)組(避免引用共享)
int[][] deep = new int[original.length][];
for (int i = 0; i < original.length; i++) {
deep[i] = original[i].clone(); // 克隆每一行
}
| 類型 | 含義 | 特點 |
|---|---|---|
| 淺拷貝(Shallow Copy) | 復(fù)制對象的引用,不復(fù)制內(nèi)部對象 | 新舊數(shù)組共享子對象 |
| 深拷貝(Deep Copy) | 遞歸復(fù)制所有層級的對象 | 完全獨立,互不影響 |
| 數(shù)組類型 | 淺拷貝是否安全? | 如何實現(xiàn)深拷貝 |
|---|---|---|
| int[], double[] 等基本類型 | ? 安全(值拷貝) | arr.clone() 即可 |
| String[] | ?? 表面安全(String 不可變) | 通常 clone() 足夠 |
| int[][](二維基本類型) | ? 不安全 | 循環(huán) + row.clone() |
| Object[](含可變對象) | ? 不安全 | 需手動深拷貝每個元素(可能遞歸) |
注意:String 雖是引用類型,但不可變(immutable),所以淺拷貝通常不會出問題。但如果是 StringBuilder[],就必須深拷貝!
| 誤區(qū) | 正確理解 |
|---|---|
| “clone() 就是深拷貝” | ? 默認是淺拷貝,除非重寫 clone() 方法 |
| “Arrays.copyOf() 是深拷貝” | ? 對多維數(shù)組仍是淺拷貝 |
| “基本類型數(shù)組不需要深拷貝” | ? 正確!因為存的是值,不是引用 |
常見陷阱 & 注意事項
| 問題 | 說明 |
|---|---|
| 空指針異常 | matrix 為 null,或某行為 null(鋸齒數(shù)組未初始化) |
| 列數(shù)不一致 | 誤以為所有行長度相同,直接用 matrix[0].length 遍歷所有行 |
| 淺拷貝問題 | 直接賦值導(dǎo)致修改副本影響原數(shù)組 |
| 內(nèi)存浪費 | 用二維數(shù)組存稀疏矩陣(此時應(yīng)考慮 Map<Pair, Value> 或稀疏表示) |
數(shù)組跟鏈表
數(shù)組(Array)和鏈表(Linked List)是兩種最基礎(chǔ)、最重要的線性數(shù)據(jù)結(jié)構(gòu)。它們在內(nèi)存布局、操作效率、適用場景上有本質(zhì)區(qū)別。掌握它們的差異,是算法設(shè)計和系統(tǒng)優(yōu)化的關(guān)鍵。
| 特性 | 數(shù)組(Array) | 鏈表(Linked List) |
|---|---|---|
| 內(nèi)存布局 | 連續(xù)內(nèi)存塊 | 非連續(xù),靠指針連接 |
| 隨機訪問 | ? O(1)(通過下標) | ? O(n)(必須遍歷) |
| 插入/刪除(中間) | ? O(n)(需移動元素) | ? O(1)(已知節(jié)點時) |
| 插入/刪除(頭部) | ? O(n)(除非用特殊技巧) | ? O(1) |
| 插入/刪除(尾部) | ? O(1)(動態(tài)數(shù)組均攤) | ? O(1)(若有 tail 指針) |
| 空間開銷 | 僅數(shù)據(jù)本身 | 每個節(jié)點額外存指針(如 next) |
| 緩存友好性 | ? 高(局部性好) | ? 低(內(nèi)存跳躍) |
| 大小固定? | 靜態(tài)數(shù)組固定;動態(tài)數(shù)組可擴容 | 動態(tài)伸縮,無需預(yù)分配 |
| 場景 | 推薦結(jié)構(gòu) | 原因 |
|---|---|---|
| 需要頻繁隨機訪問(如排序、DP) | ? 數(shù)組 | O(1) 訪問 |
| 頻繁在頭部/中間插入刪除 | ? 鏈表 | O(1) 修改指針 |
| 元素數(shù)量固定或可預(yù)估 | ? 數(shù)組 | 內(nèi)存緊湊,性能高 |
| 實現(xiàn)棧(只操作尾部) | ? 數(shù)組 or 鏈表 | 兩者都 O(1) |
| 實現(xiàn)隊列(首尾操作) | ? 鏈表 or 循環(huán)數(shù)組 | 鏈表天然支持;數(shù)組需循環(huán)緩沖 |
| 內(nèi)存敏感(小對象大量存儲) | ? 數(shù)組 | 鏈表指針開銷大 |
| 需要緩存友好(高性能計算) | ? 數(shù)組 | 連續(xù)內(nèi)存,預(yù)取高效 |
擴展:高維數(shù)組(了解即可)
// 三維數(shù)組:3 層,每層 4 行,每行 5 列
int[][][] cube = new int[3][4][5];
// 訪問
cube[0][1][2] = 10;
// 遍歷
for (int[][] layer : cube) {
for (int[] row : layer) {
for (int val : row) {
// ...
}
}
}
實際開發(fā)中,三維以上數(shù)組較少見,通常用對象封裝更清晰。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
在 Spring Boot 項目中使用分頁插件的兩種常見方式示例詳解
本文介紹了SpringBoot項目中兩種分頁插件的使用方法:MyBatis-Plus分頁插件和PageHelper插件,結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2025-10-10
解決spring.thymeleaf.cache=false不起作用的問題
這篇文章主要介紹了解決spring.thymeleaf.cache=false不起作用的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
性能爆棚的實體轉(zhuǎn)換復(fù)制工具MapStruct使用詳解
這篇文章主要為大家介紹了性能爆棚的實體轉(zhuǎn)換復(fù)制工具MapStruct使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03
Java報錯Java.net.SocketTimeoutException的幾種解決方法
在 Java 網(wǎng)絡(luò)編程中,SocketTimeoutException 通常表示在進行網(wǎng)絡(luò)操作時,等待響應(yīng)的時間超過了設(shè)定的超時時間,本文將深入探討 Java.net.SocketTimeoutException 的問題,并為開發(fā)者和環(huán)境配置者提供詳細的解決方案,需要的朋友可以參考下2024-10-10
基于JavaSwing+mysql開發(fā)一個學(xué)生社團管理系統(tǒng)設(shè)計和實現(xiàn)
項目使用Java swing+mysql開發(fā),可實現(xiàn)基礎(chǔ)數(shù)據(jù)維護、用戶登錄注冊、社團信息列表查看、社團信息添加、社團信息修改、社團信息刪除以及退出注銷等功能、界面設(shè)計比較簡單易學(xué)、適合作為Java課設(shè)設(shè)計以及學(xué)習(xí)技術(shù)使用,需要的朋友參考下吧2021-08-08
Maven在Windows中的配置以及IDE中的項目創(chuàng)建(圖文教程)
這篇文章主要介紹了Maven在Windows中的配置以及IDE中的項目創(chuàng)建(圖文教程),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09

