——10 萬條數(shù)據(jù):數(shù)組找一條需遍歷 10 萬次,哈希表 1 次即得 —— 這就是數(shù)據(jù)結(jié)構(gòu)的魅力
提到數(shù)組,很多人只知道 “是存數(shù)據(jù)的列表”,但說不清它在內(nèi)存里到底長什么樣,也不知道 “為啥電商、工業(yè)設(shè)備都愛用它”。這篇不繞理論,只講 “看得見、用得上” 的數(shù)組:先帶你看內(nèi)存里的實(shí)際效果,再講高級語言里哪些常用對象是數(shù)組做的,最后用 2 個行業(yè)案例 + 精簡對比,說清數(shù)組的用法和優(yōu)缺點(diǎn)。
一、先看內(nèi)存里的 “真實(shí)樣子”:數(shù)組是 “連續(xù)的內(nèi)存格子”
數(shù)組的核心是 “連續(xù)內(nèi)存”,咱們用 “代碼 + 內(nèi)存表格” 拆解,一看就懂。
1. 以 “int 數(shù)組” 為例:內(nèi)存是 “固定大小的連續(xù)格子”
比如在 Java 里寫代碼:int[] sensorData = {23, 25, 24, 26, 22};
(存設(shè)備 5 個時間點(diǎn)的溫度,int 占 4 字節(jié))
內(nèi)存可視化步驟:
① 系統(tǒng)分配 “連續(xù)的 5 個內(nèi)存格子”,首地址假設(shè)為0x0010;
② 按 “索引(從 0 開始)” 順序存數(shù)據(jù);
③ 訪問數(shù)據(jù)靠地址計算:首地址 + 索引×4。
對應(yīng)的內(nèi)存表格(可視化效果):
| 內(nèi)存地址(簡化) | 索引 | 存儲的數(shù)據(jù)(溫度) | 地址計算方式 |
|---|---|---|---|
| 0x0010 | 0 | 23 | 0x0010 + 0×4 |
| 0x0014 | 1 | 25 | 0x0010 + 1×4 |
| 0x0018 | 2 | 24 | 0x0010 + 2×4 |
| 0x001C | 3 | 26 | 0x0010 + 3×4 |
| 0x0020 | 4 | 22 | 0x0010 + 4×4 |
關(guān)鍵結(jié)論:
隨機(jī)訪問快(O (1)):找索引 3 的溫度,算地址
0x0010+3×4即可,不用遍歷;大小固定:初始化存 5 個 int 就占 20 字節(jié),想多存需重新申請內(nèi)存 + 復(fù)制數(shù)據(jù),擴(kuò)容麻煩。
2. 再看 “String 數(shù)組”:存 “地址”,但數(shù)組本身仍連續(xù)
比如代碼:String[] goodsNames = {"蘋果", "香蕉", "橙子"};
(String 是引用類型,數(shù)組存 “字符串的內(nèi)存地址”,每個地址占 8 字節(jié))
對應(yīng)的內(nèi)存表格:
| 數(shù)組的內(nèi)存地址(簡化) | 索引 | 存儲的字符串地址 | 字符串實(shí)際存儲位置 |
|---|---|---|---|
| 0x0030 | 0 | 0x1000 | 0x1000 存 “蘋果” |
| 0x0038 | 1 | 0x1008 | 0x1008 存 “香蕉” |
| 0x0040 | 2 | 0x1010 | 0x1010 存 “橙子” |
關(guān)鍵提醒:
數(shù)組不存字符串本身,只存 “地址”(像通訊錄存手機(jī)號,不存人);
數(shù)組格子仍連續(xù):0x0030、0x0038、0x0040 是連續(xù)的 8 字節(jié)區(qū)域。
二、高級語言里哪些常用對象,底層是數(shù)組實(shí)現(xiàn)的?
你日常用的很多 “容器”,核心都是數(shù)組,這就是數(shù)組的基礎(chǔ)性。
| 高級語言對象 | 底層實(shí)現(xiàn) | 用數(shù)組的原因 | 日常用法舉例 |
|---|---|---|---|
| Java 的 ArrayList | 動態(tài)擴(kuò)容的 Object 數(shù)組 | 隨機(jī)訪問快,自動處理擴(kuò)容(不用手動復(fù)制) |
List<String> list = new ArrayList<>();存商品 |
| Java 的 String | 不可變的 byte 數(shù)組(JDK9 后) | 按索引取字符快(如str.charAt(2)) |
String name = "張三"; 取指定字符 |
| Python 的 list | 動態(tài)擴(kuò)容數(shù)組(支持多類型) | 兼顧訪問速度和靈活性,存列表數(shù)據(jù)方便 |
goods = ["蘋果", 5, True] 存商品信息 |
| C# 的 List | 泛型數(shù)組 | 快速訪問 + 自動擴(kuò)容,適配強(qiáng)類型需求 |
List<int> scores = new List<int>();存成績 |
| 前端 JS 的 Array | 類數(shù)組動態(tài)結(jié)構(gòu)(用法一致) | 存 DOM 節(jié)點(diǎn)、列表數(shù)據(jù),按索引遍歷方便 |
const users = ["張三", "李四"]; 存用戶 |
補(bǔ)充:Java ArrayList 的動態(tài)擴(kuò)容邏輯
初始化默認(rèn)建 “容量 10 的 Object 數(shù)組”;
加第 11 個數(shù)據(jù)時,新建 “容量 15 的數(shù)組”(原容量 1.5 倍),復(fù)制舊數(shù)據(jù)后加新數(shù)據(jù);
你看到的 “靈活”,是語言幫你做了數(shù)組復(fù)制的臟活。
三、2 個行業(yè)的真實(shí)案例:什么時候必須用數(shù)組?
數(shù)組在 “按順序存、按索引查” 的場景里無可替代,看兩個典型行業(yè)用法。
1. 電商 APP:存 “商品列表” 和 “購物車數(shù)據(jù)”
場景:電商 “生鮮區(qū)商品列表”(10-100 個商品)
需求:① 按上架時間順序顯示;② 用戶點(diǎn)某商品,瞬間打開詳情;③ 滑動時快速加載下一個。
-
為什么用數(shù)組(或 ArrayList):
① 按順序存:商品按上架時間對應(yīng)數(shù)組索引,遍歷即按順序顯示;
② 按索引查快:點(diǎn)第 5 個商品(索引 4),算地址拿數(shù)據(jù),0.1 毫秒響應(yīng),無延遲;
對比坑點(diǎn):用鏈表的話,點(diǎn)第 100 個商品要跳 99 次指針,會卡頓。
2. 儀器上位機(jī)開發(fā):存 “傳感器實(shí)時采集數(shù)據(jù)”
場景:工業(yè)溫度監(jiān)控(10 個傳感器,每秒采 1 次數(shù)據(jù),存 1 小時)
需求:① 按時間順序存 3600 個數(shù)據(jù);② 快速查某秒的溫度(如第 100 秒);③ 算最近 10 秒平均溫度。
-
為什么用數(shù)組:
① 時間對應(yīng)索引:第 1 秒存索引 0,第 3600 秒存索引 3599,不用額外記時間;
② 查歷史數(shù)據(jù)快:第 100 秒的溫度直接取索引 99,不用遍歷;
③ 統(tǒng)計方便:算最近 10 秒平均,取索引 3590-3599 的數(shù)據(jù),循環(huán) 10 次即可;
對比坑點(diǎn):用哈希表要記 “時間為 key”,查數(shù)據(jù)需算哈希值,還可能沖突,不如數(shù)組直接。
四、數(shù)組的優(yōu)缺點(diǎn)是 “相對的”:3 類結(jié)構(gòu)精簡對比
數(shù)組的優(yōu)缺點(diǎn)不是絕對的,看和誰比,核心對比 3 類結(jié)構(gòu):
1. 對比鏈表
隨機(jī)訪問:數(shù)組快(O (1),算地址直接找),鏈表慢(O (n),需跳指針)→ 數(shù)組適合按索引查的場景;
中間增刪:數(shù)組慢(O (n),需移動后續(xù)元素),鏈表快(O (1),改指針)→ 數(shù)組不適合中間增刪頻繁的場景;
內(nèi)存利用率:數(shù)組高(無指針開銷),鏈表低(節(jié)點(diǎn)存指針)→ 數(shù)組適合存大量基礎(chǔ)類型數(shù)據(jù)。
2. 對比哈希表
按索引查:數(shù)組快(O (1),原生支持),哈希表慢(需算哈希值,不能直接按索引查)→ 數(shù)組適合按順序 + 索引的場景;
按關(guān)鍵詞查:數(shù)組慢(O (n),需遍歷),哈希表快(平均 O (1),算哈希找桶)→ 數(shù)組不適合按關(guān)鍵詞查的場景;
數(shù)據(jù)順序:數(shù)組有序(按索引),哈希表無序(桶 + 鏈表結(jié)構(gòu))→ 數(shù)組適合需按順序顯示的場景。
3. 對比棧
操作靈活性:數(shù)組靈活(可按索引增刪改查),棧受限(只能從棧頂增刪)→ 數(shù)組適合需靈活操作的場景,棧適合需限制操作的場景(如函數(shù)調(diào)用);
內(nèi)存開銷:兩者一致(棧底層是數(shù)組,無額外開銷)→ 棧是數(shù)組的 “受限用法”,繼承數(shù)組的內(nèi)存優(yōu)勢。
最后總結(jié):數(shù)組的 3 個核心用法,記準(zhǔn)不踩坑
需 “按順序存、按索引查” 時用數(shù)組(如電商商品列表、傳感器數(shù)據(jù));
存 “大量基礎(chǔ)類型數(shù)據(jù)”(int、byte),想省內(nèi)存時用數(shù)組(如監(jiān)控數(shù)據(jù)、統(tǒng)計數(shù)據(jù));
用 “動態(tài)數(shù)組”(ArrayList、Python list),不想管擴(kuò)容時用(覆蓋日常 90% 列表場景)。
別覺得數(shù)組 “簡單” 就忽視它 —— 它是所有數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ),也是企業(yè)開發(fā)中用得最多的結(jié)構(gòu),搞懂它的內(nèi)存本質(zhì)和用法,選結(jié)構(gòu)會比別人快 10 倍。