一、Java中Vector和SynchronizedList的區(qū)別
有了Vector為什么還要有SynchronizedList
這個(gè)問(wèn)題的答案是從 StackOverflow 中找到的。
在 JDK 1.2 之前,Collections是獨(dú)立類庫(kù),不是 JDK/JRE 中的一部分。當(dāng)時(shí)synchronized性能特別差,很多場(chǎng)景不需要使用同步方式,所以,獨(dú)立類庫(kù)的開(kāi)發(fā)者刪除了同步操作,這個(gè)應(yīng)該就是ArrayList的前身。但是,少部分場(chǎng)景還是需要使用同步,于是就有了SynchronizedList,一個(gè)可以包裝所有List子類的包裝類,這個(gè)類在幾乎所有方法上都加上了synchronized同步,這個(gè)設(shè)計(jì)與Vector相似。
古人說(shuō)“文人相輕”,其實(shí)在編碼界也是有鄙視鏈的。在這里就是:雖然我的設(shè)計(jì)和你的設(shè)計(jì)類似,但是我的設(shè)計(jì)就是比你的好。不過(guò),Collections確實(shí)設(shè)計(jì)更優(yōu)。
一個(gè)SynchronizedList實(shí)現(xiàn)所有List的同步
SynchronizedList定位是包裝類,可以包裝所有List的子類。也就是說(shuō),無(wú)論是ArrayList還是LinkedList都能過(guò)實(shí)現(xiàn)同步,完全不會(huì)修改底層數(shù)據(jù)結(jié)構(gòu),既實(shí)現(xiàn)的同步,又保留了底層接口的優(yōu)點(diǎn)。比如LinkedList的插入、刪除效率,ArrayList的順序讀取。而且,一個(gè)包裝類就解決所有List子類的同步需求,完全不需要重復(fù)實(shí)現(xiàn)一遍。
相對(duì)而言,Vector就比較霸道了,任何想要同步的隊(duì)列,都需要轉(zhuǎn)換為Vector的數(shù)組結(jié)構(gòu)。大家都知道,數(shù)組存儲(chǔ)需要連續(xù)空間,順序讀取效率表現(xiàn)優(yōu)異,但是插入和刪除效率就比較差了。
總結(jié)
Vector內(nèi)部結(jié)構(gòu)是數(shù)組,與Collections.synchronizedList(new ArrayList())類似。Vector可以指定擴(kuò)容大小,默認(rèn)是擴(kuò)容到原數(shù)組長(zhǎng)度的 2 倍;ArrayList不能指定擴(kuò)容大小,直接擴(kuò)容到原數(shù)組大小的 1.5 倍。SynchronizedList是一個(gè)包裝類,可以將List子類都包裝為同步隊(duì)列,從非線程安全隊(duì)列轉(zhuǎn)為線程安全隊(duì)列,沒(méi)有性能延遲,直接包裝即可;Vector是一個(gè)基于數(shù)組的同步隊(duì)列,其他隊(duì)列想要轉(zhuǎn)換為Vector,需要有數(shù)據(jù)拷貝。SynchronizedList的迭代器沒(méi)有做同步,需要用戶自己實(shí)現(xiàn);Vector的迭代器做好了同步,開(kāi)發(fā)人員不需要關(guān)心同步。Vector至今未標(biāo)記Deprecated,而且隨著 JDK 發(fā)布,也在更新實(shí)現(xiàn)。雖然 JDK 承諾兼容,但是一直沒(méi)有標(biāo)記過(guò)期,其用意不得而知。延伸閱讀:
二、什么是default方法
Java 8 發(fā)布以后,可以給接口添加新方法,但是,接口仍然可以和它的實(shí)現(xiàn)類保持兼容。這非常重要,因?yàn)槟汩_(kāi)發(fā)的類庫(kù)可能正在被多個(gè)開(kāi)發(fā)者廣泛的使用著。而Java 8之前,在類庫(kù)中發(fā)布了一個(gè)接口以后,如果在接口中添加一個(gè)新方法,那些實(shí)現(xiàn)了這個(gè)接口的應(yīng)用使用新版本的接口就會(huì)有崩潰的危險(xiǎn)。
有了Java 8,是不是就沒(méi)有這種危險(xiǎn)了?答案是否定的。
給接口添加default方法可能會(huì)讓某些實(shí)現(xiàn)類不可用。
讓我們看下default方法的細(xì)節(jié)。
在Java 8中,接口中的方法可以被實(shí)現(xiàn)(Java8中的static的方法也可以在接口中實(shí)現(xiàn),但這是另一個(gè)話題)。接口中被實(shí)現(xiàn)的方法叫做default方法,用關(guān)鍵字default作為修飾符來(lái)標(biāo)識(shí)。當(dāng)一個(gè)類實(shí)現(xiàn)一個(gè)接口的時(shí)候,它可以實(shí)現(xiàn)已經(jīng)在接口中被實(shí)現(xiàn)過(guò)的方法,但這不是必須的。這個(gè)類會(huì)繼承default方法。這就是為什么當(dāng)接口發(fā)生改變的時(shí)候,實(shí)現(xiàn)類不需要做改動(dòng)的原因。