Java源碼解析之接口Collection
一、圖示
二、方法定義
我們先想一想,公司如果要我們自己去封裝一些操作數(shù)組或者鏈表的工具類,我么需要封裝哪些功能呢?不妨就是統(tǒng)計(jì)其 大小,增刪改查、清空或者是查看否含有某條數(shù)據(jù)等等。而collection接口就是把這些通常操作提取出來(lái),使其更全面、更通用,那現(xiàn)在我們就來(lái)看看其源碼都有哪些方法。
//返回集合的長(zhǎng)度,如果長(zhǎng)度大于Integer.MAX_VALUE,返回Integer.MAX_VALUE int size(); //如果集合元素總數(shù)為0,返回true boolean isEmpty(); //判斷集合中是否包含指定的元素,其依據(jù)是equals()方法 boolean contains(Object o); //返回一個(gè)包含集合中所有元素的數(shù)組 Object[] toArray(); //與上個(gè)類似,只是增加了類型的轉(zhuǎn)換 <T> T[] toArray(T[] a); //向集合中加入一個(gè)元素,如果成功加入則返回true,如果加入失敗,或者因集合本身已經(jīng)包含同個(gè)元素而不再加入時(shí),返回false boolean add(E e); //從集合中刪除指定元素的單個(gè)實(shí)例 boolean remove(Object o); //如果集合包含指定集合中的所有元素,返回true boolean containsAll(Collection<?> c); //把指定集合中的所有元素添加到集合中,但在此期間,如果指定的集合發(fā)生了改變,可能出現(xiàn)意想不到的事情 boolean addAll(Collection<? extends E> c); //從集合中刪除所有包含在指定集合中的元素 boolean removeAll(Collection<?> c); //僅保留集合中包含在指定集合中的元素 boolean retainAll(Collection<?> c); //清空集合 void clear(); //將此方法抽象,是保證所有子類都覆寫(xiě)此方法,以保證equals的正確行為 boolean equals(Object o); //同上 int hashCode(); //這個(gè)方法在JDK1.8中提供了默認(rèn)的實(shí)現(xiàn),會(huì)使用Iterator的形式刪除符合條件的元素 default boolean removeIf(Predicate<? super E> filter){ Objects.requireNonNull(filter); boolean removed = false; final Iterator<E> each = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; }
三、超級(jí)實(shí)現(xiàn)類 AbstractCollection
通過(guò)以上的學(xué)習(xí),我們可以知道在collection接口中,有很多通用的方法,根據(jù)現(xiàn)有的定義以及繼承的Iterable接口,都可以在抽象方法中實(shí)現(xiàn),這樣就可以減少具體實(shí)現(xiàn)類需要實(shí)現(xiàn)的方法,所以就有了這么一個(gè)類–AbstractCollection。
首先我們來(lái)看看api文檔對(duì)這個(gè)類的大概描述:
如果要實(shí)現(xiàn)一個(gè)不可修改的集合,只需要重寫(xiě)Iterator和size接口就可以了,并且返回的Iterator需要實(shí)現(xiàn)hasNext和Next。而要實(shí)現(xiàn)一個(gè)可以修改的集合,還必須重寫(xiě)add方法,返回的Iterator還要實(shí)現(xiàn)remove接口。
接下里我們來(lái)看看其方法定義
//這個(gè)毫無(wú)疑問(wèn),是可以直接獲取的 public boolean isEmpty() { return size() == 0; } //這個(gè)方法因?yàn)镮terator的存在,可以進(jìn)行一致性封裝,這里需要注意的是對(duì)象的比較是通過(guò)equals方法,因?yàn)檎{(diào)用到了it.next()與it.hasNext(),這也是為什么文檔注釋會(huì)寫(xiě)實(shí)現(xiàn)集合類需要重寫(xiě)Iterator的這兩個(gè)方法。 public boolean contains(Object o) { Iterator<E> it = iterator(); if (o==null) { while (it.hasNext()) if (it.next()==null) return true; } else { while (it.hasNext()) if (o.equals(it.next())) return true; } return false; } //和contains類似,也是通過(guò)Iterator實(shí)現(xiàn)的,但其會(huì)調(diào)用it.remove()方法,這也是為什么文檔注釋會(huì)寫(xiě)實(shí)現(xiàn)可以修改的集合類時(shí)需要重寫(xiě)Iterator的remove方法。 public boolean remove(Object o) { //...省略,這里調(diào)用了it.remove()方法 }
還有很多方法也用到了iterator的特性,例如containAll、addAll等等,這里就不一 一說(shuō)明了。
除此之外,還有一個(gè)toArray方法,方法實(shí)現(xiàn)還有一些略微不同:
//這個(gè)實(shí)現(xiàn)相對(duì)復(fù)雜一些,可以看到擴(kuò)容最主要的手段是Arrays.copyOf()方法, //也就是需要將原數(shù)組通過(guò)復(fù)制到新的數(shù)組中來(lái)實(shí)現(xiàn)的。 //注意這里返回的順序和Iterator順序一致 //在這里實(shí)現(xiàn)是為了方便不同具體實(shí)現(xiàn)類互相轉(zhuǎn)換,我們?cè)诤罄m(xù)會(huì)多次見(jiàn)到此方法 public Object[] toArray() { //先根據(jù)當(dāng)前集合大小聲明一個(gè)數(shù)組 Object[] r = new Object[size()]; Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++) { //集合元素沒(méi)那么多,說(shuō)明不需要那么大的數(shù)組 if (! it.hasNext()) return Arrays.copyOf(r, i); //僅返回賦完值的部分 r[i] = it.next(); } //元素比從size()中獲取的更多,就需要進(jìn)一步調(diào)整數(shù)組大小 return it.hasNext() ? finishToArray(r, it) : r; } private static <T> T[] finishToArray(T[] r, Iterator<?> it) { //記錄當(dāng)前大小 int i = r.length; while (it.hasNext()) { int cap = r.length; //r的長(zhǎng)度不夠,繼續(xù)分配 if (i == cap) { //擴(kuò)充方式為cap+cap/2+1,也就是1.5倍擴(kuò)容 int newCap = cap + (cap >> 1) + 1; // 超過(guò)了最大容量,MAX_ARRAY_SIZE=Integer.MAX_VALUE-8 if (newCap - MAX_ARRAY_SIZE > 0) //重新設(shè)置cap的值 newCap = hugeCapacity(cap + 1); //對(duì)r進(jìn)行擴(kuò)容 r = Arrays.copyOf(r, newCap); } //賦值,進(jìn)入下一輪循環(huán) r[i++] = (T)it.next(); } // 由于之前擴(kuò)容是1.5倍進(jìn)行的,最后再將其設(shè)置到和r實(shí)際需要的相同 return (i == r.length) ? r : Arrays.copyOf(r, i); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // 超過(guò)了最大正整數(shù),也就是負(fù)數(shù) throw new OutOfMemoryError ("Required array size too large"); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } //和toArray()方法類似,就不再贅述,具體可以查看源碼 public <T> T[] toArray(T[] a) { //... }
除了這些,我們?cè)賮?lái)看看AbstractCollection是怎么實(shí)現(xiàn)toString方法的吧+
其是通過(guò)StringBuilder拼接了每個(gè)元素的toString完成的,不是很復(fù)雜。
我們來(lái)看看源碼吧
public String toString() { Iterator<E> it = iterator(); if (! it.hasNext()) return "[]"; StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { E e = it.next(); sb.append(e == this ? "(this Collection)" : e); if (! it.hasNext()) return sb.append(']').toString(); sb.append(',').append(' '); } }
到此這篇關(guān)于Java源碼解析之接口Collection的文章就介紹到這了,更多相關(guān)Java接口Collection 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA中Maven依賴包無(wú)法下載或?qū)氲慕鉀Q方案(系統(tǒng)缺失文件導(dǎo)致)
在配置Maven環(huán)境時(shí),可能會(huì)遇到各種報(bào)錯(cuò)問(wèn)題,首先確保Maven路徑配置正確,例如使用apache-maven-3.5.0版本,則需要在系統(tǒng)環(huán)境變量的Path中添加其bin目錄路徑,并上移優(yōu)先級(jí),接下來(lái),在Maven的conf目錄下修改settings.xml文件,將鏡像源改為阿里云2024-09-09Spring定時(shí)任務(wù)@Scheduled注解(cron表達(dá)式fixedRate?fixedDelay)
這篇文章主要為大家介紹了Spring定時(shí)任務(wù)@Scheduled注解(cron表達(dá)式fixedRate?fixedDelay)使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11java大數(shù)乘法的簡(jiǎn)單實(shí)現(xiàn) 浮點(diǎn)數(shù)乘法運(yùn)算
大數(shù)乘法可以進(jìn)行任意大小和精度的整數(shù)和浮點(diǎn)數(shù)的乘法運(yùn)算, 精確度很高, 可以用作經(jīng)融等領(lǐng)域的計(jì)算,這個(gè)是我看了一些資料, 然后自己整理實(shí)現(xiàn)的,簡(jiǎn)單測(cè)試了一下2014-01-01使用Swagger實(shí)現(xiàn)接口版本號(hào)管理方式
這篇文章主要介紹了使用Swagger實(shí)現(xiàn)接口版本號(hào)管理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10