你真的理解Java中的ArrayList嗎
1. 為什么需要ArrayList?
記得在剛剛學(xué)習(xí)Java的時(shí)候,我們首先是學(xué)習(xí)了數(shù)組,這是我們學(xué)到的第一個(gè)可以存儲(chǔ)多個(gè)對(duì)象的實(shí)例或者基本類型的具體值,數(shù)組存儲(chǔ)的特點(diǎn)如下:
- 只能存儲(chǔ)同種類型的數(shù)據(jù)。
- 在定義數(shù)組時(shí),必須指定該數(shù)組的大小,并且在不改變數(shù)組的前提下,不可修改其長度。
以上特性就會(huì)導(dǎo)致很多弊端。比如:我們往往不希望數(shù)組只能存儲(chǔ)一種數(shù)據(jù),而是希望存儲(chǔ)我們想要存儲(chǔ)的數(shù)據(jù),最好是在想要存儲(chǔ)的時(shí)候根據(jù)數(shù)據(jù)的類型指定存儲(chǔ)的類型。其次,我們也不想一開始就指定好數(shù)據(jù)的長度,而是希望這個(gè)數(shù)組的容量可以隨著我的數(shù)據(jù)的多少的改變而改變。
基于以上的弊端,Java中出現(xiàn)了集合。這是一種新的容器可以用來存儲(chǔ)數(shù)據(jù),而集合的存儲(chǔ)方式有多種,常見的有鏈?zhǔn)酱鎯?chǔ)(LinkedList)和順序存儲(chǔ)(ArrayList)。
鏈?zhǔn)酱鎯?chǔ)底層是用一個(gè)個(gè)節(jié)點(diǎn)(Node)鏈接而成的,每個(gè)節(jié)點(diǎn)都存儲(chǔ)著一個(gè)對(duì)象值和下一個(gè)節(jié)點(diǎn)的位置(或上一個(gè)節(jié)點(diǎn)的位置)。
順序存儲(chǔ)底層是用一個(gè)數(shù)組存儲(chǔ)數(shù)據(jù)的,對(duì)于數(shù)組的弊端,順序存儲(chǔ)集合底層使用了ensureCapacity這個(gè)方法不斷擴(kuò)容,ensureCapacity這個(gè)單詞字面翻譯是 保證能力。顧名思義,由于底層是一個(gè)數(shù)組,當(dāng)我們存入一個(gè)對(duì)象時(shí),我們需要保證數(shù)組是有空余位置的,因此在添加元素的時(shí)候,Java源碼會(huì)先經(jīng)過這個(gè)方法進(jìn)行判斷底層數(shù)組是否滿了,若滿了則會(huì)擴(kuò)容數(shù)組(上面提到數(shù)組是不能直接擴(kuò)容的,這里實(shí)際上是重新創(chuàng)建了一個(gè)更大空間的數(shù)組并把元素“搬運(yùn)”過去)。這樣就解決了數(shù)組的一個(gè)弊端。而對(duì)于另一個(gè)弊端,Java則是巧妙的運(yùn)用了泛型。泛型的內(nèi)容非常繁多,這里結(jié)合實(shí)例希望大家可以更好的理解。
想象一下現(xiàn)在有一個(gè)需求,需要你實(shí)現(xiàn)一個(gè)的多值加法,但傳入的參數(shù)的類型是不確定的,可以有Integer,String,Double等等。這時(shí)候如果你用的是數(shù)組作為參數(shù),那么那你肯定會(huì)想,最粗糙的方法是分別寫多個(gè)加法方法,對(duì)應(yīng)不同的類型,但很明顯,代碼可讀性極差,那如果使用Object數(shù)組,然后再根據(jù)數(shù)據(jù)類型,轉(zhuǎn)換為對(duì)應(yīng)的類型再計(jì)算?這樣也存在弊端!你根本不知道需要轉(zhuǎn)換為什么類型才合適。因此,針對(duì)這種情況,使用泛型集合是最合適的,我們只需要在傳入?yún)?shù)的時(shí)候使用泛型類型,而因?yàn)椴煌愋陀?jì)算的過程是一致的,因此結(jié)果并沒有差別,也不會(huì)導(dǎo)致報(bào)錯(cuò)。
2. ArrayList底層是如何實(shí)現(xiàn)的?
簡單介紹了ArrayList的用途以及和數(shù)組的區(qū)別,那么根據(jù)上面的講解,你應(yīng)該大致了解它的實(shí)現(xiàn)原理了吧!
先不看源碼,如果你有一些數(shù)據(jù)結(jié)構(gòu)與算法的基礎(chǔ)的話,你應(yīng)該可以馬上得出下面結(jié)論:先在ArrayList類定義一個(gè)數(shù)組,接著定義一個(gè)添加,一個(gè)刪除,一個(gè)查詢,一個(gè)修改方法。實(shí)際上是對(duì)數(shù)組的操作,那么,刪除和添加可能需要移動(dòng)大量的元素,這些都是在源碼中實(shí)現(xiàn),但對(duì)應(yīng)到效率也會(huì)很低,其次還需要一個(gè)擴(kuò)容數(shù)組的方法。
如果你能想到上面這些,恭喜你,你已經(jīng)掌握的很不錯(cuò)。事實(shí)上,ArrayList的源碼確實(shí)包含以上方法,只不過還需要加上迭代器以及構(gòu)造方法等。迭代器的出現(xiàn)是為了適應(yīng)增強(qiáng)for語句(后面會(huì)細(xì)說),構(gòu)造方法是為了初始化集合。
3. 結(jié)合源碼分析主要成員變量
ArrayList繼承AbstractList這個(gè)抽象類和List接口
List
接口繼承Collection接口(實(shí)際上集合還有map集合等)
而Collection則是繼承了Iterable(可迭代的),Collection中包含了集合中通用的方法,包括增刪改查,只不過都未實(shí)現(xiàn)。而Iterable則是只有一個(gè)forEach方法,提供迭代。
接著我們回到ArrayList類,這是底層維護(hù)的數(shù)組,實(shí)際上對(duì)象存儲(chǔ)的地方
記錄集合的長度
返回集合的長度
判斷集合是否為空
根據(jù)索引獲取元素
添加元素
添加元素到指定位置
刪除元素
內(nèi)部類的next方法實(shí)現(xiàn)迭代功能(我們平時(shí)使用增強(qiáng)for語句的判斷條件就是根據(jù)判斷是否有next值來實(shí)現(xiàn)的)
4. 個(gè)人的一點(diǎn)總結(jié)
Java的設(shè)計(jì)者很巧妙的設(shè)計(jì)了Java中的每個(gè)功能,很多時(shí)候,我們會(huì)覺得說我手動(dòng)實(shí)現(xiàn)簡單的集合不需要這么復(fù)雜的代碼呀?甚至有些功能都不需要單獨(dú)作為一個(gè)方法。但這就是Java的魅力??!
以前剛學(xué)代碼的我們,把代碼全都丟到main方法里面,我們會(huì)覺得提取出來是多么復(fù)雜,但當(dāng)我們知道功能是有區(qū)別的,我們才知道這樣子做的用處。
曾經(jīng)有個(gè)老師這么對(duì)我說,他說你知道為什么我們要費(fèi)盡心思去設(shè)計(jì)各種類之間的關(guān)系,接口,抽象類,泛型等等嗎?那時(shí)候的我一臉茫然,他對(duì)我說,打個(gè)比方,你見過賣水果的店里還賣手機(jī)的嗎?我聽完后恍然大悟,對(duì)于一個(gè)小城鎮(zhèn),確實(shí)可能存在一個(gè)小店賣著各種雜七雜八的東西,但一個(gè)千萬人口的大城市,是做不到的,這是格局啊!各種功能,各種設(shè)施都應(yīng)該井井有條,關(guān)系明確。面向?qū)ο笠埠?,設(shè)計(jì)模式也好,一切的功能都是為了大型程序做準(zhǔn)備,這也是為什么Java一直可以大型應(yīng)用的后端程序語言之一。
到此這篇關(guān)于Java中ArrayList的文章就介紹到這了,更多相關(guān)Java中ArrayList內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaFX實(shí)現(xiàn)簡易時(shí)鐘效果
這篇文章主要為大家詳細(xì)介紹了JavaFX實(shí)現(xiàn)簡易時(shí)鐘效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11Spring Boot 2 整合 QuartJob 實(shí)現(xiàn)定時(shí)器實(shí)時(shí)管理功能
Quartz是一個(gè)完全由java編寫的開源作業(yè)調(diào)度框架,形式簡易,功能強(qiáng)大。接下來通過本文給大家分享Spring Boot 2 整合 QuartJob 實(shí)現(xiàn)定時(shí)器實(shí)時(shí)管理功能,感興趣的朋友一起看看吧2019-11-11org.springframework.beans.BeanInstantiationException異常解決
本文主要介紹了org.springframework.beans.BeanInstantiationException異常解決,大多數(shù)情況下,這個(gè)異常是由于簡單的配置錯(cuò)誤或者代碼問題導(dǎo)致的,下面就來具體解決一下2024-03-03springboot項(xiàng)目編寫發(fā)送異常日志到企微工具包的操作方法
本文介紹了Springboot項(xiàng)目如何編寫發(fā)送異常日志到企業(yè)微信的工具包,內(nèi)容包括創(chuàng)建基礎(chǔ)Bean、配置類、pom依賴等步驟,并展示了如何通過nacos進(jìn)行配置,這為開發(fā)者提供了一種有效的日志管理方案,方便快速定位和處理項(xiàng)目中的異常問題,感興趣的朋友跟隨小編一起看看吧2024-09-09

spring-cloud入門之eureka-client(服務(wù)注冊)