- Java語言的特性
Java的三大特性:封裝碴裙、繼承稠炬、多態(tài)
封裝:隱藏對象的屬性和實現(xiàn)細(xì)節(jié),僅對外提供公共的訪問方式屯烦。好處:提高重用性和安全性豁生。
繼承:從已有的類中派生出新的類兔毒,新的類能吸收已有類的數(shù)據(jù)屬性和行為,平能擴(kuò)展新的能力甸箱。好處:提高代碼的重用性育叁。
多態(tài):同一操作作用于不同的對象,可以有不同的解釋芍殖,產(chǎn)生不同的執(zhí)行結(jié)果豪嗽,就是多態(tài),簡單點說:就是用父類的引用指向子類的對象豌骏。
表現(xiàn)形式:方法重寫龟梦,方法重載,接口和接口的繼承窃躲,類和類的繼承
方法重載:同一個類中计贰,有多個方法名相同,但參數(shù)列表不同
方法重寫:子類重寫父類的方法
好處:當(dāng)父類中的方法蒂窒,無法滿足子類的需求時躁倒,子類可以對父類的方法進(jìn)行擴(kuò)展。
- Java的基本數(shù)據(jù)類型
類型 | 字節(jié)大小 | 長度 |
---|---|---|
byte | 1 | -128-127 |
char | 2 | 0-65535 |
short | 2 | -215-215-1 |
int | 4 | -231-231-1 |
long | 8 | -263-263-1 |
float | 4 | -2128-2128 |
double | 8 | -21024-21024 |
boolean | 1/8 | true洒琢、false |
- String和StringBuffer崖疤、StringBuilder的區(qū)別
- String:用final修飾的char[]數(shù)組土砂,不可變;
- StringBuffer:synchronized修飾方法,線程安全,通過System.copyArray()方法動態(tài)修改;
- StringBuild:線程不安全;
- Java類的加載順序
- 首先加載父類的靜態(tài)字段或者靜態(tài)語句塊;
- 子類的靜態(tài)字段或者靜態(tài)語句塊
- 父類的普通變量以及語句塊
- 父類的構(gòu)造方法被加載
- 子類的變量或者語句塊被加載
- 子類的構(gòu)造方法被加載
- Java類加載的過程
加載-驗證-準(zhǔn)備-解析-初始化-使用-卸載
驗證-準(zhǔn)備-解析 也被稱為連接階段
-
加載:把代碼數(shù)據(jù)加載到內(nèi)存中妻率,即JVM將字節(jié)碼從各個位置(網(wǎng)絡(luò)饺蚊、磁盤等)轉(zhuǎn)化為二進(jìn)制字節(jié)流加載到內(nèi)存中亭姥,接著會為這個類在JVM的方法區(qū)創(chuàng)建一個對應(yīng)的class對象即纲,這個class對象就是這個類各種數(shù)據(jù)的訪問入口。
- 驗證:虛擬機(jī)對代碼數(shù)據(jù)進(jìn)行效驗谭网,查看是否按照J(rèn)VM規(guī)范編寫拇舀。
JVM規(guī)范效驗:JVM會對字節(jié)流進(jìn)行文件格式效驗,判斷其是否符合蜻底;
JVM規(guī)范:是否能被當(dāng)前版本的虛擬機(jī)處理骄崩;
代碼邏輯效驗:JVM會對代碼組成的數(shù)據(jù)流和控制流進(jìn)行效驗,確保JVM運行該字節(jié)碼文件后不會出現(xiàn)致命錯誤薄辅; -
準(zhǔn)備:JVM開始為類變量分配內(nèi)存并初始化要拂。
內(nèi)存分配的對象:Java中的變量有【類變量】和【類成員變量】兩者類型,類變量指的是被static修飾的變量站楚,而其他所有類型的變量都屬于類成員變量脱惰。
在準(zhǔn)備階段,JVM只會為類變量分配內(nèi)存窿春,而不會為類成員變量分配內(nèi)存拉一。
類成員變量的內(nèi)存分配需要等到初始化階段才開始采盒。
初始化的類型:在準(zhǔn)備階段,JVM會為類成員變量分配內(nèi)存蔚润,并為其初始化磅氨。但是這里的初始化指的是為變量賦予,Java語言中該數(shù)據(jù)類型的零值嫡纠,而不是用戶代碼里初始化的值烦租。 -
解析:JVM針對類或接口、字段除盏、類方法叉橱、接口方法、方法類型者蠕、方法句柄和調(diào)用點限定符7類引用進(jìn)行解析窃祝。
這個階段的主要任務(wù)是將其在常量池中的符號引用替換成直接其在內(nèi)存中直接引用。 - 初始化:JVM會根據(jù)語句執(zhí)行順序?qū)︻悓ο筮M(jìn)行初始化踱侣。
- 使用:當(dāng)JVM完成初始化階段之后粪小,JVM便開始從入口方法開始執(zhí)行用戶的程序代碼。
- 卸載:當(dāng)用戶程序代碼執(zhí)行完畢后泻仙,JVM便開始銷毀創(chuàng)建的class對象糕再,最后負(fù)責(zé)運行的JVM也退出內(nèi)存量没。
- Java類加載器
- Bootstrap ClassLoader:最頂層的加載類玉转,主要加載核心類庫,也就是環(huán)境變量下面%JRE_HOME/lib下的rt.jar殴蹄、resource.jar究抓、charsets.jar和class等。還可以通過啟動jvm時指定位置;
-
Extention ClassLoader:擴(kuò)展的類加載器袭灯,加載目錄%JRE_HOME/lib/ext目錄下的jar包和class文件刺下。
還可以加載-Djava.ext.dirs選項指定的目錄; - Appclass Loader:也稱為SystemAppClass稽荧,加載當(dāng)前應(yīng)用的classpath的所有類橘茉;
- Custom ClassLoader:自定義加載類;
- Java雙親委派機(jī)制
定義:當(dāng)某個類加載器需要加載某個.class文件時姨丈,它首先把這個任務(wù)委托給他的上級類加載器畅卓,遞歸這個操作,如果上級的類加載器沒有加載蟋恬,自己才會去加載這個類翁潘。
作用:
- 防止重復(fù)加載同一個.class。通過委托去向上問一問歼争,加載過了拜马,就不用再加載一遍了渗勘,保證數(shù)據(jù)安全。
- 保證核心.class不能被篡改俩莽。透過委托方式旺坠,不會去篡改核心.class,及時篡改了也不會去加載豹绪,即使加載了也不會是同一個.class對象了价淌。不同的類加載器加載同一個.class也不是同一個Class對象,這樣保證了Class執(zhí)行安全瞒津。
- Java反射機(jī)制(http://www.reibang.com/p/9be58ee20dee)
定義:在運行狀態(tài)中蝉衣,對于任意一個類,都能夠知道這個類的所有屬性和方法巷蚪;對于任意一個對象病毡,都能夠調(diào)用它的任意方法和屬性;這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為java的反射機(jī)制屁柏。
反射機(jī)制的相關(guān)類:
- CLass類:代表類的實體啦膜,在運行的Java應(yīng)用程序中表示類和接口
- Field類:代表類的成員變量(成員變量也稱為類的屬性)
- Method類:代表類的方法
- Constructor:代表類的構(gòu)造方法
- Java的內(nèi)存模型(http://www.reibang.com/p/0ecf020614cb)
包括程序計數(shù)器、 虛擬機(jī)棧淌喻、本地方法棧僧家、方法區(qū)、堆
- 程序計數(shù)器:主要功能是記錄當(dāng)前線程執(zhí)行程序的位置裸删,通過改變計算數(shù)值來確定執(zhí)行下一條指令八拱。每個線程的創(chuàng)建,都會創(chuàng)建一個程序計數(shù)器涯塔,并且對于每個線程而言都是相互獨立的肌稻。
- 虛擬機(jī)棧:主要功能是臨時存儲線程執(zhí)行到的每個方法需要的參數(shù),其內(nèi)存空間在編譯時就已確定匕荸。每創(chuàng)建一個線程爹谭,則創(chuàng)建一個虛擬機(jī)棧。線程每執(zhí)行到一個方法榛搔,對應(yīng)的棧里就會創(chuàng)建一個棧幀诺凡,棧幀會存儲局部變量表、動態(tài)鏈接践惑、操作數(shù)棧和方法出口等信息腹泌,執(zhí)行方法,棧幀入棧童本,方法執(zhí)行完真屯,棧幀出棧。
- 本地方法棧:和Java虛擬機(jī)棧一樣穷娱,只是記錄native方法執(zhí)行绑蔫。
- 堆:堆內(nèi)存是存放所有對象實例运沦,也是jvm的GC主要對象。
- 方法區(qū):主要存儲虛擬機(jī)棧加載類信息配深、常量携添、靜態(tài)變量。
- Java的特性
- 原子性:指一個操作或多個操作要么全部執(zhí)行篓叶,且執(zhí)行的過程不會被任何因素打斷烈掠,要么就都不執(zhí)行;(處理器會自動保證基本的內(nèi)存操作是原子性的;使用線程鎖保證原子性缸托;使用緩存鎖保證原子性 eg:CAS)左敌。
- 可見性:指當(dāng)一個線程修改了線程共享變量的值,其他線程能夠立即得知這個修改(比如使用volatile)俐镐。
-
有序性:即程序執(zhí)行的順序按照代碼的先后順序執(zhí)行矫限;
(Java內(nèi)存模型中的程序天然有序性可以總結(jié)為一句話:如果在本線程內(nèi)觀察,所有操作都是有序的佩抹;如果在一個線程中觀察另一個線程叼风,所有操作都是無序的。不過可以通過synchronized禁止指令重排)
- JVM垃圾回收機(jī)制http://www.reibang.com/p/23f8249886c6
一棍苹、引用計數(shù)法:給每個對象添加一個計數(shù)器无宿,當(dāng)有地方引用該對象時計數(shù)器加1,當(dāng)引用失效時計數(shù)器減1枢里,用對象計數(shù)器是否為0來判斷對象是否可被回收孽鸡。
缺點:無法解決循環(huán)引用的問題。
二坡垫、可達(dá)性分析算法:通過GC ROOT的對象作為搜索起始點梭灿,通過引用向下搜索画侣,所走過的路徑稱為引用鏈冰悠。通過對象是否有到達(dá)引用鏈的路徑來判斷對象是否可被回收。
可作為GC ROOT對象:虛擬機(jī)棧中引用的對象配乱、方法區(qū)中類靜態(tài)屬性引用的對象溉卓,方法區(qū)中常量引用的對象、本地方法棧中JNI引用的對象搬泥。
- 垃圾回收算法
一桑寨、標(biāo)記-清除算法:最基礎(chǔ)的一種垃圾回收算法,它分為兩部分忿檩,先把內(nèi)存區(qū)域中的這些對象進(jìn)行標(biāo)記尉尾,哪些屬于可回收標(biāo)記出來,然后把這些垃圾領(lǐng)出來清理掉燥透。
缺點:會造成內(nèi)存碎片沙咏,需要開辟大內(nèi)存空間時辨图,因為是不連續(xù)的,導(dǎo)致用不了而浪費肢藐。
二故河、復(fù)制算法:在標(biāo)記清楚算法基礎(chǔ)上演化而來,解決標(biāo)記清除算法的內(nèi)存碎片問題吆豹。將可用內(nèi)存按容量劃分為大小相等的兩塊鱼的,每次只使用其中一塊。當(dāng)這一塊的內(nèi)存用完了痘煤,就將還存活的對象復(fù)制到另外一塊上面凑阶,然后再把已使用過的內(nèi)存空間一次性清理掉。保證了內(nèi)存連續(xù)可用衷快,內(nèi)存分配時也就不用考慮內(nèi)存碎片等復(fù)雜情況晌砾。
缺點:只能使用一半內(nèi)存
三、標(biāo)記-整理算法:標(biāo)記-整理算法標(biāo)記過程仍然與標(biāo)記-清楚算法一樣烦磁,但后續(xù)步驟不是直接對可回收對象進(jìn)行清理养匈,而是讓所有存活的對象都向一端移動,而清理掉端邊界以外的內(nèi)存區(qū)域都伪。
標(biāo)記-整理算法解決了內(nèi)存碎片問題呕乎,也規(guī)避了復(fù)制算法只能利用一半內(nèi)存區(qū)域的弊端。標(biāo)記-整理算法對內(nèi)存變動更頻繁陨晶,需要整理所有的存活對象的引用地址猬仁,在效率上比復(fù)制算法要差很多。
四先誉、分代收集算法:分代收集算法嚴(yán)格來說并不是一種思想或理論湿刽,而是融合上述3種基礎(chǔ)的算法思想,而產(chǎn)生的針對不同情況所采用不同算法的一套組合拳褐耳,根據(jù)對象存活周期的不同將內(nèi)存劃分為幾塊诈闺。
在新生代中,每次垃圾收集時都發(fā)現(xiàn)有大批對象死去铃芦,只有少量存活雅镊,那就選用復(fù)制算法,只需要付出少量存活對象的復(fù)制成本就可以完成收集刃滓。
在老年代中仁烹,因為對象存活率高、沒有額外空間對它進(jìn)行分配擔(dān)保咧虎,就必須使用標(biāo)記-清理算法-或者標(biāo)記-整理算法來進(jìn)行回收卓缰。
- Java多線程
繼承Thread類、實現(xiàn)Runable接口、線程池創(chuàng)建多線程征唬、實現(xiàn)Callable接口
- Java線程池
- corePoolSize:核心線程池大小
- maximumPoolSize:線程池最大大小
- keepAliveTime:線程存活保持時間
- timeUnit:時間單位
- workQueue:任務(wù)隊列
- threadFactory:線程工廠
- handler:線程飽和策略
- Java 常用線程池
-
newFixedThreadPool
固定線程池震叮,核心線程數(shù)和最大線程數(shù)固定相等,而空閑存活時間為0毫秒鳍鸵,說明此參數(shù)也無意義苇瓣,工作隊列為最大為Integer.MAX_VALUE大小的阻塞隊列。當(dāng)執(zhí)行任務(wù)時偿乖,如果線程都很忙击罪,就會丟到工作隊列等有空閑線程時再執(zhí)行,隊列滿就執(zhí)行默認(rèn)的拒絕策略贪薪。 -
newCachedThreadPool
帶緩沖線程池媳禁,從構(gòu)造看核心線程數(shù)為0,最大線程數(shù)為Integer最大值大小画切,超過0個的空閑線程在60秒后銷毀竣稽,SynchronousQueue這是一個直接提交的隊列,意味著每個新任務(wù)都會有線程來執(zhí)行霍弹,如果線程池有可用線程則執(zhí)行任務(wù)毫别,沒有的話就創(chuàng)建一個來執(zhí)行,線程池中的線程數(shù)不確定典格,一般建議執(zhí)行速度較快較小的線程岛宦,不然這個最大線程池邊界過大容易造成內(nèi)存溢出。 -
newSingleThreadExecutor
單線程線程池耍缴,核心線程數(shù)和最大線程數(shù)均為1砾肺,空閑線程存活0毫秒同樣無意思,意味著每次只執(zhí)行一個線程防嗡,多余的先存儲到工作隊列变汪,一個一個執(zhí)行,保證了線程的順序執(zhí)行蚁趁。 -
newScheduledThreadPool
調(diào)度線程池裙盾,即按一定的周期執(zhí)行任務(wù),即定時任務(wù)荣德,對ThreadPoolExecutor進(jìn)行了包裝而已闷煤。
- Java線程同步和異步
- 同步:單線程執(zhí)行童芹,所有操作都是同步的涮瞻。
- 異步:并發(fā)都是異步的。
- Java線程之Join假褪、Yield和Sheep,Wait和notify
- Yield:暫停當(dāng)前線程執(zhí)行署咽,讓其他線程參與競爭,系統(tǒng)選擇其他相同的或者更高優(yōu)先級的線程;
- Join:是當(dāng)前的線程暫停執(zhí)行宁否,等待調(diào)用該方法的線程結(jié)束后再繼續(xù)執(zhí)行本線程窒升;
- Sleep:屬于Thread類,暫停線程執(zhí)行慕匠,線程進(jìn)入阻塞狀態(tài)饱须,讓出CPU,不會釋放對象鎖台谊,到指定時間會自動醒過來蓉媳;
- Wait:必須在synchronized內(nèi)部執(zhí)行,屬于Object類,暫停線程執(zhí)行锅铅,線程進(jìn)入休眠狀態(tài)酪呻,釋放對象鎖,加入等待對象池盐须,只有調(diào)用notify()和notifyAll()方法才可以執(zhí)行玩荠;
- Java之死鎖
死鎖:死鎖是操作系統(tǒng)層面的一個錯我,是進(jìn)程死鎖的簡稱贼邓。
必要條件:
- 互斥條件:即當(dāng)資源被一個線程使用阶冈,別的線程不能使用。
- 不剝奪條件:資源請求者不能強(qiáng)制從占有者手中奪取資源塑径,資源只能由資源占有者主動釋放眼溶。
- 請求和保持:即當(dāng)資源請求者在請求其他的資源的同時保持對原有資源的占有。
- 循環(huán)等待:即存在一個等待隊列晓勇,P1占有P2的資源堂飞,P2占有P3的資源,P3占有P1的資源绑咱,這樣既形成了一個等待環(huán)路绰筛。
- Java之volatile關(guān)鍵字
- 保證了不同線程對這個變量進(jìn)行操作時的可見性,即一個線程修改了每個變量的值描融,新值對其他線程來說是立即可見的铝噩。
- 禁止進(jìn)行指令重排序。
- Java同步鎖-synchronized關(guān)鍵字和Lock接口
synchronized:可以修飾靜態(tài)方法窿克、成員函數(shù)骏庸,還可以直接定義代碼塊
(https://cloud.tencent.com/developer/article/1465413)
- 對成員函數(shù)加鎖,必須獲得該類的實例對象的鎖才能進(jìn)入同步塊年叮;
- 對靜態(tài)方法加鎖具被,必須獲得該類的鎖才能進(jìn)入同步塊;
- 對同步塊加入class只损,執(zhí)行前必須獲得該class類的鎖一姿;
- 對同步塊加入Instance七咧,執(zhí)行前必須先獲得實例對象的鎖;
- synchronized鎖的實現(xiàn):
有兩種方式:它們的底層實現(xiàn)一樣叮叹,在進(jìn)入同步代碼之前先獲取鎖艾栋,獲取到鎖之后鎖的計數(shù)器+1,同步代碼執(zhí)行完鎖的計數(shù)器-1蛉顽,如果獲取失敗就阻塞式等待鎖的釋放蝗砾。
同步方式識別不同。
- 對方法上鎖:通過flags標(biāo)志
- 構(gòu)造同步代碼塊:通過monitorenter和monitorexit指令操作
- synchronized鎖的底層實現(xiàn)原理:
在JVM中携冤,對象分成三部分存在:對象頭遥诉、實例數(shù)據(jù)、對其填充噪叙。
對象頭是synchronized實現(xiàn)鎖的基礎(chǔ)矮锈,因為synchronized申請鎖、上鎖睁蕾、釋放鎖都與對象頭有關(guān)苞笨。
對象頭主要結(jié)構(gòu)由Mark Word 和 CLass Metadata Address,其中Mark Word存儲著鎖信息子眶。
JDK6之后瀑凝,synchronized優(yōu)化之后有四個狀態(tài):無狀態(tài)鎖、偏向鎖臭杰、輕量級鎖粤咪、重量級鎖,鎖的狀態(tài)在對象頭Mark Word 中都有記錄渴杆,在申請鎖寥枝、鎖升級等過程中JVM都需要讀取對象的Mark down數(shù)據(jù)。
- synchronized鎖膨脹
偏向鎖:減少統(tǒng)一線程獲取鎖的代價磁奖。在大多數(shù)情況下囊拜,鎖不存在多線程競爭,總是由同一線程多次獲得比搭,那么此時即使偏向的冠跷。
核心思想:如果一個線程獲得了鎖,那么鎖就進(jìn)入偏向模式身诺,此時 Mark down的結(jié)構(gòu)也就變?yōu)槠蜴i結(jié)構(gòu)蜜托,當(dāng)該線程再次請求鎖時,無需再做任何同步操作霉赡,即獲取鎖的過程只需要檢查 Mark down的鎖標(biāo)記位為偏向鎖以及當(dāng)前線程ID等于Mark down的ThreadID即可橄务。
輕量級鎖:輕量級鎖是由偏向鎖升級而來,當(dāng)存在第二個線程申請同一個鎖對象時同廉,偏向鎖就會立即升級為輕量級鎖仪糖。注意這里的第二個線程只是申請鎖柑司,不存在兩個線程同時競爭鎖迫肖,可以是一前一后的交替
執(zhí)行同步塊锅劝。
重量級鎖:重量級鎖是由輕量級鎖升級而來,當(dāng)同一時間有多個線程競爭鎖時蟆湖,鎖就會被升級成重量級鎖故爵,此時其申請鎖帶來的開銷也就變大。
- 鎖消除:消除鎖是虛擬機(jī)另外一種鎖的優(yōu)化隅津,這種優(yōu)化更徹底诬垂,在JIT編譯時,對運行上下文進(jìn)行掃描伦仍,
去除不可能存在競爭的鎖结窘。
- 鎖優(yōu)化:鎖粗化是虛擬機(jī)對另一種極端情況的優(yōu)化處理,通過擴(kuò)大鎖的范圍充蓝,避免重復(fù)加鎖和釋放鎖隧枫。
- 自旋鎖:通過讓線程執(zhí)行循環(huán)等待鎖的釋放,不讓出CPU谓苟。如果等到鎖官脓,就順利進(jìn)入臨界區(qū)。如果還不能獲得鎖涝焙,那么久掛起卑笨。但是如果鎖被其他線程長時間占用,一直不釋放CPU仑撞,會帶來許多的性能開銷赤兴。
- 自適應(yīng)自旋鎖:相當(dāng)于對自旋鎖的進(jìn)一步優(yōu)化。它的自旋次數(shù)不再固定隧哮,其自旋的次數(shù)由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態(tài)決定搀缠,這就解決了自旋鎖帶來的缺點。
- Java之Lock接口
- 定義:是一個接口近迁,用來手動的獲取和釋放鎖艺普,并且發(fā)生異常時不會主動的釋放鎖,所有必須在try...catch塊中鉴竭,在finally中釋放鎖歧譬,保證鎖一定會被釋放,不會發(fā)生死鎖搏存。
-
原理:(https://blog.csdn.net/future234/article/details/80576623)
AQS(隊列同步器瑰步,雙向鏈表) + int值 + CAS自旋
- synchronized和lock的區(qū)別
- 首先synchronized是java內(nèi)置關(guān)鍵字,Lock是Java類;
- synchronized無法判斷是否獲取鎖的狀態(tài)璧眠,Lock可以判斷是否獲取到鎖;
- synchronized會自動釋放鎖缩焦,Lock需在finally中手工釋放鎖读虏,否則容易造成線程死鎖;
- synchronized的鎖可重入、不可中斷袁滥、非公平盖桥。Lock鎖可重入、可判斷题翻、公平和非公平都可實現(xiàn);
- Lock建議使用在低鎖沖突的情況下;
- Java中的引用類型
1揩徊、強(qiáng)引用代碼中普遍存在的類似"Object obj = new Object()"這類的引用,只要強(qiáng)引用還存在嵌赠,垃圾收集器永遠(yuǎn)不會回收掉被引用的對象塑荒。
2、軟引用描述有些還有用但并非必需的對象姜挺。在系統(tǒng)將要發(fā)生內(nèi)存溢出異常之前齿税,將會把這些對象列進(jìn)回收范圍進(jìn)行二次回收。如果這次回收還沒有足夠的內(nèi)存炊豪,才會拋出內(nèi)存溢出異常凌箕。Java中的類SoftReference表示軟引用。
3溜在、弱引用描述非必需對象陌知。被弱引用關(guān)聯(lián)的對象只能生存到下一次垃圾回收之前,垃圾收集器工作之后掖肋,無論當(dāng)前內(nèi)存是否足夠仆葡,都會回收掉只被弱引用關(guān)聯(lián)的對象。Java中的類WeakReference表示弱引用志笼。
4沿盅、虛引用這個引用存在的唯一目的就是在這個對象被收集器回收時收到一個系統(tǒng)通知,被虛引用關(guān)聯(lián)的對象纫溃,和其生存時間完全沒關(guān)系腰涧。Java中的類PhantomReference表示虛引用。
- Java集合
- Array:數(shù)組是相同類型數(shù)據(jù)的有序集合紊浩,在堆中被分配連續(xù)空間窖铡,通過下標(biāo)尋找,查找速度快坊谁,插入慢费彼。
- List:鏈表是一種物理存儲單元上非連續(xù)、非順序的存儲結(jié)構(gòu)口芍,數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針連接次序?qū)崿F(xiàn)的箍铲。每個鏈表包含多個節(jié)點,節(jié)點包含兩個部分鬓椭,一個是數(shù)據(jù)域颠猴,用來存儲數(shù)據(jù)关划,一個是引用域(相當(dāng)于指針,雙向鏈表有兩個指針翘瓮,分別指向上一個和下一個節(jié)點)贮折,指向下個節(jié)點。查找慢春畔,插入脱货、刪除快岛都。
- Map:是一種鍵-值對集合律姨,Map集合中的每一個元素都包含一個鍵對象和一個值對象
- ArrayList:
- 內(nèi)部采用數(shù)組實現(xiàn),默認(rèn)大小10;
- 擴(kuò)容newCapacity = oldCapacity + (oldCapacity >> 1);
- 擴(kuò)容時 調(diào)用native System.arrayCopy 方法拷貝;
- 可以存在多個null;
- LinkedList:
- 內(nèi)部采用雙向鏈表存儲;
- 可以存在多個null;
- Vector:
- 內(nèi)部數(shù)組實現(xiàn);
- 默認(rèn)大小為10,capacityIncrement設(shè)置自增長大小 沒有則自增張一倍;
- 內(nèi)部方法被synchronized修飾臼疫,線程安全;
- HashMap:(http://www.reibang.com/p/ee0de4c99f87)
- 內(nèi)部由數(shù)組+鏈表+紅黑樹實現(xiàn);
- 默認(rèn)大小16择份,默認(rèn)負(fù)載系數(shù)0.75,閾值
threshold = loadFactor(負(fù)載系數(shù)) * capacity(容量)
;- resize()擴(kuò)容直接擴(kuò)大一倍
newThr = oldThr << 1; // double threshold
;- 當(dāng)鏈表長度大于8且容量大于64烫堤,轉(zhuǎn)紅黑數(shù) 當(dāng)鏈表長度小于6荣赶,還原成數(shù)組;
- 擴(kuò)容因子默認(rèn)0.75,是根據(jù)泊松分布(二項分布)測得;
- key和value可以為null鸽斟,key至多只有一個;
- 樹:樹是一種抽象數(shù)據(jù)類型或是實現(xiàn)這種抽象數(shù)據(jù)類型的數(shù)據(jù)結(jié)構(gòu)拔创,用來模擬具有樹狀結(jié)構(gòu)性質(zhì)的數(shù)據(jù)集合。
(http://www.reibang.com/p/683ccf7b4712)
特點:
- 每個節(jié)點有零個或多個子節(jié)點富蓄;
- 沒有父節(jié)點的節(jié)點稱為根節(jié)點剩燥;
- 每個非根節(jié)點有且只有一個父節(jié)點;
- 除了根節(jié)點外立倍,每個子節(jié)點可以分為多個不相交的子樹灭红;
- 二叉樹:每個節(jié)點最多含有兩個子節(jié)點的樹稱為二叉樹
- 滿二叉樹:一顆有n層的二叉樹,除第n層外口注,每層都有兩個子節(jié)點
- 完全二叉樹:假設(shè)二叉樹有h層变擒,除第好層外,其他各層的節(jié)點數(shù)均已達(dá)到最大個數(shù)(1至h-1層為滿二叉樹)寝志,第h層所有的節(jié)點都集中在最左邊娇斑,這棵樹就是滿二叉樹。
- 二叉查找樹:又稱為二叉搜索樹材部、有序二叉樹毫缆、排序二叉樹
特點:
- 若任意節(jié)點的左子樹不空,則左子樹上所有節(jié)點的值均小于它的跟節(jié)點的值败富;
- 若任意節(jié)點的右子樹不空悔醋,則右子樹上所有節(jié)點的值均大于他的根節(jié)點的值;
- 任意節(jié)點的左兽叮、右子樹也分別為二叉查找樹芬骄;
- 沒有鍵值相等的點猾愿;
- 平衡二叉樹(AVL樹)
因為二叉樹某些情況會退化成鏈條表,時間復(fù)雜度O(n)账阻,效率低下蒂秘,這時需要平衡二叉樹。它是嚴(yán)格的平衡二叉樹淘太,平衡條件必須滿足姻僧,所有只有通過旋轉(zhuǎn)保持平衡,而旋轉(zhuǎn)是非常耗時的蒲牧,適用于插入和刪除次數(shù)比較少撇贺,但查找多的情況。
特點:
- 左樹所有節(jié)點比根節(jié)點小冰抢,右樹所有節(jié)點比根節(jié)點大
- 左樹和右樹的高度最大差值為1
- 紅黑樹
通過對任何一條從跟到葉子的路徑上各個節(jié)點著色的方式的限制松嘶,紅黑樹確保沒有一條路徑會比其他路徑長出兩倍,它是一種弱平衡二叉樹挎扰,相比AVL樹來說翠订,它的旋轉(zhuǎn)次數(shù)少,對于搜索遵倦、插入尽超、刪除操作較多的情況下,優(yōu)先用紅黑樹梧躺。
特點:
- 每個節(jié)點是黑色或紅色;
- Root節(jié)點一定是黑色;
- Null節(jié)點一定是黑色;
- 不能出現(xiàn)連續(xù)的紅色節(jié)點;
- 從任意一個節(jié)點達(dá)到子節(jié)點的黑色數(shù)目相同;
- Java值傳遞和引用傳遞(https://mp.weixin.qq.com/s/Qp6Cc0mlRLnrToNy5-3zeg)
(可以說是Java不同數(shù)據(jù)類型儲存的方式不同導(dǎo)致有值傳遞和引用傳遞這種說法)
形參:方法被調(diào)用時需要傳遞進(jìn)來的參數(shù)似谁,如:func(int a)中的a,它只有在func被調(diào)用期間a才有意義燥狰,也就是會被分配內(nèi)存空間奖唯,在方法func執(zhí)行完成后板惑,a就會被銷毀釋放空間伍掀,也就是不存在了
實參:方法被調(diào)用時是傳入的實際值刘莹,它在方法被調(diào)用前就已經(jīng)被初始化并且在方法被調(diào)用時傳入。
值傳遞:在方法被調(diào)用時目代,實參通過形參把它的內(nèi)容副本傳入方法內(nèi)部屈梁,此時形參接收到的內(nèi)容是實參值的一個拷貝,因此在方法內(nèi)對形參的任何操作榛了,都僅僅是對這個副本的操作在讶,不影響原始值的內(nèi)容。
引用傳遞:”引用”也就是指向真實內(nèi)容的地址值霜大,在方法調(diào)用時构哺,實參的地址通過方法調(diào)用被傳遞給相應(yīng)的形參,在方法體內(nèi),形參和實參指向通愉快內(nèi)存地址曙强,對形參的操作會影響的真實內(nèi)容残拐。
基本數(shù)據(jù)類型:我們聲明并初始化基本數(shù)據(jù)類型的局部變量時,變量名以及字面量值都是存儲在棧中碟嘴,而且是真實的內(nèi)容溪食。在值傳遞過程中,我們知道棧幀是私有的娜扇、獨立的错沃,傳遞過去的值是拷貝過去的副本,然后繼續(xù)修改變量的值雀瓢,不會影響原值枢析。
引用數(shù)據(jù)類型:”引用”也就是指向真實內(nèi)容的地址值,在方法調(diào)用時致燥,實參的地址通過方法調(diào)用被傳遞給相應(yīng)的形參登疗,在方法體內(nèi)排截,形參和實參指向通愉快內(nèi)存地址嫌蚤,對形參的操作會影響的真實內(nèi)容。引用傳遞断傲,也是拷貝副本脱吱,但是它們的引用地址指向同一個,看起來像是同一個认罩,實際上重新new一個對象會發(fā)現(xiàn)箱蝠,原來的對象沒有改變。
在Java中所有的參數(shù)傳遞垦垂,不管基本類型還是引用類型宦搬,都是值傳遞,或者說是副本傳遞劫拗。
只是在傳遞過程中:
如果是對基本數(shù)據(jù)類型的數(shù)據(jù)進(jìn)行操作间校,由于原始內(nèi)容和副本都是存儲實際值,并且是在不同的棧區(qū)页慷,因此形參的操作憔足,不影響原始內(nèi)容。
如果是對引用類型的數(shù)據(jù)進(jìn)行操作酒繁,分兩種情況滓彰,一種是形參和實參保持指向同一個對象地址,則形參的操作州袒,會影響實參指向的對象的內(nèi)容揭绑。一種是形參被改動指向新的對象地址(如重新賦值引用),則形參的操作郎哭,不會影響實參指向的對象的內(nèi)容他匪。