摘要:隨機(jī)訪問數(shù)據(jù)是相對(duì)于順序訪問數(shù)據(jù)而言,例如鏈表的形式。方法將容器中的元素轉(zhuǎn)化為數(shù)組的形式。在函數(shù)中,對(duì)容量每次擴(kuò)展的大小,并且會(huì)檢查是否會(huì)超過設(shè)定的最大數(shù)組長度。如果長度超過了限定值,則以原容量為底線,返回一個(gè)最大容量。
ArrayList繼承自AbstractList,AbstractList為“random access”的數(shù)組提供了基本的實(shí)現(xiàn)。隨機(jī)訪問數(shù)據(jù)是相對(duì)于順序訪問數(shù)據(jù)而言,例如鏈表的形式。AbstractSequentialList為鏈表形式的順序訪問提供了基本實(shí)現(xiàn)。AbstractList提供了默認(rèn)的隨機(jī)訪問數(shù)據(jù)的iterator。AbstractList繼承自AbstractCollection,AbstractCollection為Collection提供了基本實(shí)現(xiàn)。
java.util.AbstractCollection
containsAbstractCollection實(shí)現(xiàn)了查詢是否包含某一個(gè)元素的方法。最好使用Iterator遍歷集合中的元素,因?yàn)榭梢云帘渭蟽?nèi)部元素存儲(chǔ)的具體實(shí)現(xiàn),并且根據(jù)不同的數(shù)據(jù)存儲(chǔ)特點(diǎn),優(yōu)化訪問策略。這里還可以正確查找null元素,需要注意的是對(duì)null元素的查詢需要特別的處理,有時(shí)候自己實(shí)現(xiàn)方法時(shí),往往會(huì)忽略傳入?yún)?shù)為null時(shí)的處理,導(dǎo)致方法無法處理特殊情況。
public boolean contains(Object o) { IteratortoArrayit = 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; }
toArray方法將容器中的元素轉(zhuǎn)化為數(shù)組的形式。這里元素的復(fù)制,采用的是直接復(fù)制引用。這里還考慮到了并發(fā)運(yùn)算時(shí),元素?cái)?shù)量在復(fù)制時(shí)產(chǎn)生變化的情況,當(dāng)數(shù)量減少時(shí),就用Arrays.copy()截取結(jié)果。當(dāng)數(shù)量增加時(shí),會(huì)調(diào)用finishToArray函數(shù)擴(kuò)容。
public Object[] toArray() { // Estimate size of array; be prepared to see more or fewer elements Object[] r = new Object[size()]; Iteratorit = iterator(); for (int i = 0; i < r.length; i++) { if (! it.hasNext()) // fewer elements than expected return Arrays.copyOf(r, i); r[i] = it.next(); } return it.hasNext() ? finishToArray(r, it) : r; }
在finishToArray函數(shù)中,對(duì)容量每次擴(kuò)展1/2+1的大小,并且會(huì)檢查是否會(huì)超過設(shè)定的最大數(shù)組長度MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8。如果長度超過了限定值,則以原容量+1為底線,返回一個(gè)最大容量。最后返回的數(shù)組也會(huì)修剪掉多余的位置。
private staticT[] finishToArray(T[] r, Iterator> it) { int i = r.length; while (it.hasNext()) { int cap = r.length; if (i == cap) { int newCap = cap + (cap >> 1) + 1; // overflow-conscious code if (newCap - MAX_ARRAY_SIZE > 0) newCap = hugeCapacity(cap + 1); r = Arrays.copyOf(r, newCap); } r[i++] = (T)it.next(); } // trim if overallocated return (i == r.length) ? r : Arrays.copyOf(r, i); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError ("Required array size too large"); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
這里有一個(gè)toArray的重載,需要傳入一個(gè)數(shù)組作為參數(shù),據(jù)我觀察,目的是將集合中的元素存入指定的數(shù)組,重利用已有數(shù)組的存儲(chǔ)。如果元素過多,而目標(biāo)數(shù)組容納不下,只能重新申請(qǐng)數(shù)組來進(jìn)行存儲(chǔ)。
publicremoveAllT[] toArray(T[] a) { // Estimate size of array; be prepared to see more or fewer elements int size = size(); T[] r = a.length >= size ? a : (T[])java.lang.reflect.Array .newInstance(a.getClass().getComponentType(), size); Iterator it = iterator(); for (int i = 0; i < r.length; i++) { if (! it.hasNext()) { // fewer elements than expected if (a == r) { //利用的原數(shù)組,且元素不足,則補(bǔ)null表示結(jié)束 r[i] = null; // null-terminate } else if (a.length < i) { //元素較少,但數(shù)量超過原始數(shù)組,只能用新數(shù)組 return Arrays.copyOf(r, i); } else { //元素減少,導(dǎo)致原始數(shù)組可以容納下,則copy回原始數(shù)組,折騰唄 System.arraycopy(r, 0, a, 0, i); if (a.length > i) { a[i] = null; } } return a; } r[i] = (T)it.next(); } // more elements than expected return it.hasNext() ? finishToArray(r, it) : r; }
removeAll方法刪除目標(biāo)集合中的所有重疊元素。Iterator可以做到在遍歷時(shí),安全的刪除元素,而通過index循環(huán)刪除則可能導(dǎo)致index偏移。
public boolean removeAll(Collection> c) { Objects.requireNonNull(c); boolean modified = false; Iterator> it = iterator(); while (it.hasNext()) { if (c.contains(it.next())) { it.remove(); modified = true; } } return modified; }toString
AbstractCollection的toString實(shí)現(xiàn),比較令我震驚的是e == this的作用。這里為什么要判斷打印的內(nèi)容是否為自己本身?因?yàn)?b>sb.append(e == this ? "(this Collection)" : e);會(huì)調(diào)用e的toString函數(shù)來生成字符串,若不加判斷,則會(huì)形成無限的toString遞歸調(diào)用。我猜想一下,估計(jì)當(dāng)時(shí)toString的實(shí)現(xiàn)者沒有注意到該問題的存在,直到該bug出現(xiàn),腦洞不大還真難想起來這個(gè)問題。
public String toString() { Iteratorit = 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(" "); } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/67735.html
摘要:說一說迭代器通過集合對(duì)象獲取其對(duì)應(yīng)的對(duì)象判斷是否存在下一個(gè)元素取出該元素并將迭代器對(duì)象指向下一個(gè)元素取出元素的方式迭代器。對(duì)于使用容器者而言,具體的實(shí)現(xiàn)不重要,只要通過容器獲取到該實(shí)現(xiàn)的迭代器的對(duì)象即可,也就是方法。 前言 歡迎關(guān)注微信公眾號(hào):Coder編程獲取最新原創(chuàng)技術(shù)文章和相關(guān)免費(fèi)學(xué)習(xí)資料,隨時(shí)隨地學(xué)習(xí)技術(shù)知識(shí)!** 本章主要介紹Collection集合相關(guān)知識(shí),結(jié)合面試中會(huì)提到...
摘要:容器相關(guān)的操作及其源碼分析說明本文是基于分析的。通常,我們通過迭代器來遍歷集合。是接口所特有的,在接口中,通過返回一個(gè)對(duì)象。為了偷懶啊,底層使用了迭代器。即返回的和原在元素上保持一致,但不可修改。 容器相關(guān)的操作及其源碼分析 說明 1、本文是基于JDK 7 分析的。JDK 8 待我工作了得好好研究下。Lambda、Stream。 2、本文會(huì)貼出大量的官方注釋文檔,強(qiáng)迫自己學(xué)英語,篇幅...
摘要:值得注意的是,的迭代器是否要調(diào)用方法是由要?jiǎng)h除的目標(biāo)是否數(shù)組的元素決定的,如果不存在這樣的元素,則下面的代碼并不會(huì)出現(xiàn)異常, java.util.Arrays$ArrayList(下文:Arrays$ArrayList)是java.util.Arrays的私有靜態(tài)內(nèi)部類,他實(shí)現(xiàn)的接口,繼承的父類幾乎和java.util.ArrayList(下文:ArrayList)相同,既然是私有的,...
摘要:加載因子是哈希表在其容量自動(dòng)增加之前可以達(dá)到多滿的一種尺度。當(dāng)哈希表中的條目數(shù)超出了加載因子與當(dāng)前容量的乘積時(shí),則要對(duì)該哈希表進(jìn)行操作即重建內(nèi)部數(shù)據(jù)結(jié)構(gòu),從而哈希表將具有大約兩倍的桶數(shù)。成員變量每個(gè)對(duì)由封裝,存在了對(duì)象數(shù)組中。 雖是讀書筆記,但是如轉(zhuǎn)載請(qǐng)注明出處 http://segmentfault.com/blog/exploring/ .. 拒絕伸手復(fù)制黨 LinkedLis...
摘要:它主要做了件事初始化容器,并將元素添加到容器里維護(hù)這樣我們?cè)僬{(diào)用的方法直接就返回了,不需要再次遍歷和統(tǒng)計(jì)的過程。維護(hù)實(shí)時(shí)的維護(hù),及時(shí)刪除總結(jié)整體上是對(duì)底層的二次封裝,很好的處理了各種細(xì)節(jié),比如子容器的判空處理,的計(jì)算效率,的維護(hù)等。 在日常開發(fā)中我們通常有需要對(duì) List 容器進(jìn)行分組的情況,比如對(duì)下面的list數(shù)據(jù)根據(jù)name字段來進(jìn)行分組: [ { date...
閱讀 3206·2023-04-26 03:06
閱讀 3694·2021-11-22 09:34
閱讀 1142·2021-10-08 10:05
閱讀 3041·2021-09-22 15:53
閱讀 3543·2021-09-14 18:05
閱讀 1409·2021-08-05 09:56
閱讀 1906·2019-08-30 15:56
閱讀 2133·2019-08-29 11:02