數(shù)組,你不一定了解的全面
在上一章節(jié)中已經(jīng)對(duì)數(shù)據(jù)結(jié)構(gòu)的基本概念有了了解,主要就是數(shù)據(jù)結(jié)構(gòu)研究的三個(gè)方面(邏輯結(jié)構(gòu)、存儲(chǔ)結(jié)構(gòu)、算法)。還有兩個(gè)重要的詞匯:時(shí)間效率和空間效率。這一節(jié)開(kāi)始了解最基本的數(shù)據(jù)結(jié)構(gòu)-數(shù)組。
一、數(shù)組的基本概念
1、什么是數(shù)組?
在平時(shí)使用最多的恐怕就是數(shù)組了吧,
它是使用最廣泛的一種數(shù)據(jù)結(jié)構(gòu),它是相同數(shù)據(jù)類(lèi)型(可以是基本類(lèi)型也可以是自定義類(lèi)型)的元素按一定順序排列的集合,它們?cè)趦?nèi)存中按照這個(gè)先后順序連續(xù)存放在一起。有一維數(shù)組,二維數(shù)組,多維數(shù)組。
通俗的理解就是我們一般把一群羊或者一群牛放在一個(gè)圈里面,這個(gè)圈就相當(dāng)于數(shù)組容器,每一個(gè)羊相當(dāng)于一個(gè)元素。
以上這個(gè)概念需要知道這幾個(gè)詞匯:相同數(shù)據(jù)類(lèi)型、一定順序排列、集合、內(nèi)存先后存放。
2、如何聲明一個(gè)數(shù)組
從標(biāo)題就可以看到,聲明和創(chuàng)建一個(gè)數(shù)組是兩個(gè)不同的過(guò)程。聲明的作用就好像是告訴別人我要去洗澡,創(chuàng)建的作用就好像是我真正的去洗澡了(比喻不當(dāng)哈哈)。那如何聲明數(shù)組呢?
- int[] students ;
- int students [];
從上面我們看到這里有兩種方式,但一般推薦第一種。畢竟第一種看起來(lái)可讀性更好一點(diǎn)。
3、如何創(chuàng)建一個(gè)數(shù)組
在我們知道了如何聲明數(shù)組之后,接下來(lái)就是我們?nèi)绾蝿?chuàng)建一個(gè)數(shù)組。不同的語(yǔ)言創(chuàng)建一個(gè)數(shù)組的方式還是不一樣的,但是大體上一樣,這里給出java的幾種方式。
- //第一種:
- int [] students = new int[50];
- //第二種:
- String [] colors = {"red","blue","black"};
從上面可以發(fā)現(xiàn)創(chuàng)建一個(gè)數(shù)組如此簡(jiǎn)單,別急,這三種方式里面其實(shí)還是有很多知識(shí)點(diǎn)需要掌握的。其實(shí)數(shù)組的創(chuàng)建其中有一個(gè)環(huán)節(jié)叫做數(shù)組的初始化。舉個(gè)例子,我創(chuàng)建了一個(gè)數(shù)組,但是一開(kāi)始數(shù)組容器里面可能還沒(méi)有這些值。那什么時(shí)候才有了這些值呢?也就是系統(tǒng)什么時(shí)候把我聲明的那些red、blue等等裝到數(shù)組容器里面的呢?這個(gè)過(guò)程就是數(shù)組的初始化。數(shù)組是如何初始化的呢?
數(shù)組的初始化分為靜態(tài)初始化、動(dòng)態(tài)初始化:
- 靜態(tài)初始化:數(shù)組在初始化時(shí)由程序員顯式指定每個(gè)數(shù)組元素的初始值。而數(shù)組長(zhǎng)度由系統(tǒng)決定。在上面創(chuàng)建數(shù)組的那三種方式中,第三種就是靜態(tài)初始化。第二種也是,但是屬于靜態(tài)初始化的簡(jiǎn)化方式。
- 動(dòng)態(tài)初始化:動(dòng)態(tài)初始化時(shí)則必須指定元素個(gè)數(shù)。動(dòng)態(tài)初始化時(shí)數(shù)組元素個(gè)數(shù)未知因此必須指定。上面第一種就是。
4、數(shù)組的分類(lèi)
可能看到這個(gè)標(biāo)題有一個(gè)疑問(wèn),數(shù)組還有分類(lèi)嗎?不就是把相同類(lèi)型的元素放在一起嘛。其實(shí)不然。下面給你好好的分一下類(lèi):
**按照是否有序分:**有序數(shù)組和無(wú)序數(shù)組。
按照數(shù)組能否擴(kuò)容分:靜態(tài)數(shù)組和動(dòng)態(tài)數(shù)組。
先來(lái)看靜態(tài)數(shù)組:在編譯期間在棧中分配好內(nèi)存的數(shù)組,在運(yùn)行期間不能改變存儲(chǔ)空間,運(yùn)行后由系統(tǒng)自動(dòng)釋放。
再來(lái)看動(dòng)態(tài)數(shù)組:動(dòng)態(tài)數(shù)組,是相對(duì)于靜態(tài)數(shù)組而言。靜態(tài)數(shù)組的長(zhǎng)度是預(yù)先定義好的,在整個(gè)程序中,一旦給定大小后就無(wú)法改變。而動(dòng)態(tài)數(shù)組則不然,它可以隨程序需要而重新指定大小。動(dòng)態(tài)數(shù)組的內(nèi)存空間是從堆(heap)上分配(即動(dòng)態(tài)分配)的。是通過(guò)執(zhí)行代碼而為其分配存儲(chǔ)空間。當(dāng)程序執(zhí)行到這些語(yǔ)句時(shí),才為其分配。程序員自己負(fù)責(zé)釋放內(nèi)存。
java中動(dòng)態(tài)數(shù)組的原理
現(xiàn)有一個(gè)數(shù)組:
int [] data = new int[5];
該數(shù)組已經(jīng)無(wú)法繼續(xù)添加元素了,所以我們?cè)俪跏蓟粋€(gè)新的數(shù)組,其容量為10,即數(shù)組arr容量的2倍:int [] newData = new int [10];
然后將原數(shù)組的所有元素全部都賦值給新的數(shù)組。
再將原數(shù)組的引用 arr指向 新的數(shù)組。
靜態(tài)數(shù)組和動(dòng)態(tài)數(shù)組的比較:
對(duì)于靜態(tài)數(shù)組,其創(chuàng)建非常方便,使用完也無(wú)需釋放,要引用也簡(jiǎn)單,但是創(chuàng)建后無(wú)法改變其大小是其致命弱點(diǎn)!對(duì)于動(dòng)態(tài)數(shù)組,其創(chuàng)建麻煩,使用完必須由程序員自己釋放,否則嚴(yán)重會(huì)引起內(nèi)存泄露。但其使用非常靈活,能根據(jù)程序需要?jiǎng)討B(tài)分配大小。
二、數(shù)組的特點(diǎn)
在上面掌握了其基本概念之后,再來(lái)看一下數(shù)組有什么特點(diǎn),數(shù)組的特點(diǎn)也是根據(jù)其分類(lèi)來(lái)的,比如說(shuō)有序數(shù)組其特點(diǎn)肯定就是有序,我們方便查找數(shù)據(jù),無(wú)序的我們方面插入刪除數(shù)據(jù)這些。所以這里講的特點(diǎn)是所有數(shù)組共有的特點(diǎn),也就是一般性特點(diǎn):又回到了之前發(fā)過(guò)的文章,特點(diǎn)就是來(lái)看時(shí)間效率和空間效率的。
1.數(shù)組的長(zhǎng)度固定的,超過(guò)長(zhǎng)度時(shí),只能創(chuàng)建一個(gè)新的數(shù)組,并把舊的數(shù)組的值傳進(jìn)去方可;
2.數(shù)組的存儲(chǔ)類(lèi)型是單一的,同一數(shù)組只能存儲(chǔ)同一數(shù)據(jù)類(lèi)型的數(shù)據(jù)。
3.數(shù)組只能通過(guò)下標(biāo)來(lái)訪問(wèn)數(shù)據(jù)
三、數(shù)組的使用場(chǎng)景
數(shù)組較容器,最大的優(yōu)點(diǎn)就是效率。在Java中,數(shù)組是一種效率最高的存儲(chǔ)和隨機(jī)訪問(wèn)對(duì)象引用序列的方式,數(shù)組就是一個(gè)簡(jiǎn)單的線性序列,這使得元素訪問(wèn)非??焖?, 數(shù)組的優(yōu)點(diǎn)是效率高,但為此,所付出的代價(jià)就是數(shù)組對(duì)象的大小被固定。這也使得在工作中,數(shù)組并不實(shí)用。我們應(yīng)該優(yōu)選java中的容器,而不是數(shù)組。
四、數(shù)組的底層實(shí)現(xiàn)
這里的底層實(shí)現(xiàn)也是相比較于java語(yǔ)言來(lái)說(shuō)的,比如在以后的文章里面,像鏈表這樣的數(shù)據(jù)結(jié)構(gòu)我也會(huì)配合Java中鏈表實(shí)現(xiàn)的容器來(lái)配合著說(shuō)。
Java提供了很棒的集合API和集合類(lèi)如:ArrayList、HashMap,他們內(nèi)部都是基于數(shù)組。java如果程序嘗試訪問(wèn)無(wú)效的數(shù)組索引的話jvm會(huì)拋出ArrayIndexOutOfBoundException。
Java語(yǔ)言中,數(shù)組的實(shí)現(xiàn)原理是什么?
這個(gè)涉及到編譯原理的問(wèn)題,我只能說(shuō),這是一個(gè)編譯規(guī)范。在規(guī)范中比如:int[]中的int告訴計(jì)算機(jī)這是一個(gè)整型數(shù)據(jù),[]告訴計(jì)算機(jī)這是一個(gè)連續(xù)存儲(chǔ)的內(nèi)存地址空間,簡(jiǎn)單點(diǎn)說(shuō)一個(gè)連續(xù)數(shù)據(jù)的存儲(chǔ)空間就是數(shù)組,數(shù)組只是一個(gè)名稱(chēng)!!數(shù)組在Java里是一種特殊類(lèi)型,有別于普通的“類(lèi)的實(shí)例”的對(duì)象。
以HotSpot VM為例,答案是在數(shù)組對(duì)象的對(duì)象頭里有一個(gè)length字段,記錄數(shù)組長(zhǎng)度。arraylength字節(jié)碼的實(shí)現(xiàn)只要去讀那個(gè)_length字段即可。JVM 中數(shù)組對(duì)象是一種特殊的對(duì)象,它的Object Header 比普通對(duì)象多了一個(gè)word 來(lái)存儲(chǔ)數(shù)組的長(zhǎng)度,length 會(huì)編譯成對(duì)應(yīng)的字節(jié)碼讀取這個(gè)field 就可以了。
本文轉(zhuǎn)載自微信公眾號(hào)「愚公要移山」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系愚公要移山公眾號(hào)。