從源碼到場景,用五分鐘講透 Array 和 ArrayList 的差異
大家好!我是小米,一個29歲、樂于分享技術(shù)的小米。今天我們來聊聊一個經(jīng)常出現(xiàn)在社招面試中的問題——Array 和 ArrayList 有何區(qū)別?
當(dāng)時我剛跳槽到新公司,在面試時,面試官突然拋出一個看似簡單的問題:“能說說 Array 和 ArrayList 的區(qū)別嗎?”表面看,這問題容易得像開水白菜,但實際上,它藏著大招。
面試場景回放
面試官一臉嚴(yán)肅地盯著我,說:“Array 和 ArrayList 的區(qū)別不僅僅是理論知識,更體現(xiàn)在實際開發(fā)的運用中。”
我點點頭,快速在腦海中梳理了一遍,回答道:
定義和存儲方式
Array(數(shù)組):
數(shù)組是 Java 中最基本的數(shù)據(jù)結(jié)構(gòu)之一,它是一個固定大小的容器,用來存儲相同數(shù)據(jù)類型的元素。數(shù)組的長度在創(chuàng)建時就確定了,后續(xù)無法更改。
圖片
ArrayList:
ArrayList 是 Java 提供的一個動態(tài)數(shù)組類,它可以隨著數(shù)據(jù)量的增加自動擴容,且屬于 Java Collections Framework。其底層實際上是用數(shù)組實現(xiàn)的。
圖片
面試官點了點頭,追問:它們存儲數(shù)據(jù)時有什么不同?
我繼續(xù)回答:數(shù)組是直接存儲數(shù)據(jù),而 ArrayList 內(nèi)部通過包裝類來存儲對象。也就是說,ArrayList 需要裝箱和拆箱,會有一定的性能開銷。
大小是否可變
Array:數(shù)組的大小一旦初始化就不能改變。如果需要更大的存儲空間,必須重新創(chuàng)建一個更大的數(shù)組,并將原有數(shù)據(jù)復(fù)制過去。
圖片
ArrayList:大小是動態(tài)變化的,它會根據(jù)需要自動擴容,開發(fā)者無需手動管理。
圖片
性能比較
- 數(shù)組性能更高:數(shù)組在訪問和操作時性能更高,因為它是直接操作內(nèi)存中的元素,沒有額外的開銷。
- ArrayList 靈活但略慢:ArrayList 的操作需要頻繁地裝箱和拆箱,尤其是當(dāng)擴容時,它需要創(chuàng)建一個新數(shù)組并將數(shù)據(jù)復(fù)制過去,性能會受到影響。
支持的操作
Array:
數(shù)組是相對“原始”的數(shù)據(jù)結(jié)構(gòu),支持索引訪問,但不支持增刪操作。
ArrayList:
ArrayList 提供了豐富的操作方法,比如 add()、remove() 和 contains() 等,非常方便。
圖片
是否支持泛型
Array:數(shù)組在定義時支持泛型,但是泛型數(shù)組的初始化有一定的局限性,例如不能直接創(chuàng)建泛型數(shù)組。
圖片
ArrayList:ArrayList 是 Collections Framework 的一部分,支持泛型,使用更為靈活。
圖片
多線程支持
- Array:數(shù)組本身是線程安全的,因為它是最基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),沒有額外的線程同步機制。
- ArrayList:ArrayList 不是線程安全的。如果需要在多線程環(huán)境中使用,可以用 Collections.synchronizedList() 包裝它,或者直接使用線程安全的 CopyOnWriteArrayList。
真實場景下的選擇
在實際開發(fā)中,我們?nèi)绾芜x擇呢?
- 需要高性能、固定大小的場景:優(yōu)先選擇數(shù)組,比如處理大量的數(shù)學(xué)計算或內(nèi)存敏感的任務(wù)。
- 需要靈活操作或動態(tài)擴展:ArrayList 是更好的選擇,比如存儲用戶輸入的數(shù)據(jù)或動態(tài)生成的數(shù)據(jù)。
寫代碼小貼士
記住,Array 和 ArrayList 都有自己的適用場景。在面試中,除了理論講清楚,還可以舉一些實際的例子來說明它們的用法。最后,別忘了提到擴展知識點,比如 LinkedList 和 CopyOnWriteArrayList,這樣面試官一定會對你刮目相看!