亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

JDK源碼閱讀——ArrayList

2019-11-11 04:14:59
字體:
來源:轉載
供稿:網友

如同C語言中字符數組向String過渡一樣,作為面向對象語言,自然而然的出現了由Object[]數據形成的集合。本文從JDK源碼出發簡單探討一下ArrayList的幾個重要方法。

Fields

//序列化Id保證了集合是可以進行RPC通信的 PRivate static final long serialVersionUID = 8683452581122892189L; //作為一個普通Object[]數組,集合的默認長度是10 private static final int DEFAULT_CAPACITY = 10; //這里聲明一個空Object數組,用來標示空集合 private static final Object[] EMPTY_ELEMENTDATA = {}; //默認長度的Object數組 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //真正存儲數據的的Object數組,transient保證不會參與序列化 transient Object[] elementData; //當前ArrayList的長度 private int size;

構造器

//當用戶指定了容量的時候,elementData就是新new出來的Object數組,如果長度指定為0則等于聲明的空Object數組。不支持負數長度。 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } //若用戶沒有指定長度,構造一個默認長度為10的空Object數組。 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //如果傳入的是集合類,則拷貝出一個新的Object數組存放用戶輸入的數組內容 public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) //根據c的聲明方式不同,c.toArray()得到的結果類型是不同的。雖然elementData聲明的是Object數組,但是如果c.toArray()不是Object數組類型,elementData無法存放Object類型。所以這里做了判斷,如果是這種情況,重新拷貝一份新的Object數組。 //關于這點特性可以參考http://blog.csdn.net/aitangyong/article/details/30274749?utm_source=tuicool&utm_medium=referral if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // 如果傳入的長度為0,則elementData等于聲明的空數組 this.elementData = EMPTY_ELEMENTDATA; } }

內部方法

//由于elementData會進行擴容,擴容機制見下文。所以會生成一些沒有用的位置,通過trimToSize方法啊重新生成一段實際長度的Object數組。長度全為有效長度。 public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } } //核心功能,提前擴容。當需要擴容的空間很大的時候,可以通過這個以前一次性擴容,否則會一次次慢慢擴容。這種方式效率很高。 private void ensureExplicitCapacity(int minCapacity) { modCount++; // 如果用戶希望的大小大于當前的容量,則進行擴容 if (minCapacity - elementData.length > 0) grow(minCapacity); } //擴容方法 private void grow(int minCapacity) { // 新容量為老容量的1.5倍 int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); //如果新容量依然沒有達到用戶期望的長度,則以用戶輸入的容量為準擴容。 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //如果新容量已經特別大接近極限了,進行最大程度的擴容 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } //最大程度擴容方法 private static int hugeCapacity(int minCapacity) { //如果用戶期待的容量很大,比最大整數還大就是負數了,則OOM if (minCapacity < 0) // overflow throw new OutOfMemoryError(); //否則就給最大的空間 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } //新增元素 public void add(int index, E element) { //檢查索引,不合法就異常 rangeCheckForAdd(index); //進行擴容,首先進行+1擴容 ensureCapacityInternal(size + 1); //將index后面的統一往后移動,所以add效率很低 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } //刪除元素 public E remove(int index) { //索引合法性檢查 rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) //統一往前移動 System.arraycopy(elementData, index+1, elementData, index,numMoved); //把最后一個空出來的賦值null,方便gc回收 elementData[--size] = null; // clear to let GC do its work return oldValue; }//取子列表方法public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); } //檢查參數 static void subListRangeCheck(int fromIndex, int toIndex, int size) { if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); if (toIndex > size) throw new IndexOutOfBoundsException("toIndex = " + toIndex); if (fromIndex > toIndex) throw new IllegalArgumentException("fromIndex(" + fromIndex +") > toIndex(" + toIndex + ")"); } private class SubList extends AbstractList<E> implements Randomaccess { private final AbstractList<E> parent; private final int parentOffset; private final int offset; int size; //依然是原始數組,不過是聲明了一個不同的其實與結尾坐標,總體邏輯和外部類ArrayList基本相同 SubList(AbstractList<E> parent, int offset, int fromIndex, int toIndex) { this.parent = parent; this.parentOffset = fromIndex; this.offset = offset + fromIndex; this.size = toIndex - fromIndex; this.modCount = ArrayList.this.modCount; } //jdk1.7以后List本身有了sort功能,不用再通過Collections.sort來排序了 @Override @SuppressWarnings("unchecked") public void sort(Comparator<? super E> c) { final int expectedModCount = modCount; Arrays.sort((E[]) elementData, 0, size, c); if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; }

總結

ArrayList的源碼重點在于: 1. 擴容的時候按照原容量的1.5倍擴容 2. 若需要的容量很大,可以通過ensureCapacity進行提前一步到位擴容,或者直接通過構造器聲明一個大的ArrayList。 3. 對Object[]進行操作的時候都是通過System.arraycopy進行的,這是一個native方法,直接操作內存,等同于C語言中的底層方法。 4. 關于默認長度為什么是10,還不是很明白。按照StackOverFlow的說法是作為一個List長度沒有必要是2的次冪。10不大不小,剛好夠用(通過數據分析得到)。但是我仍然不理解為什么HashMap就要是2的次冪。等看完HashMap再來回答這個問題。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品视频精品视频| 国产精品福利在线观看网址| 97超级碰在线看视频免费在线看| 一道本无吗dⅴd在线播放一区| 69视频在线播放| 日韩av成人在线观看| 亚洲精品国产拍免费91在线| 成人h视频在线| 97视频免费在线观看| 欧美激情免费在线| 国产精品一区二区av影院萌芽| 日韩经典中文字幕| 亚洲国产精品人人爽夜夜爽| 伊人激情综合网| 97国产精品视频| 57pao精品| 国产精品www网站| 国内外成人免费激情在线视频网站| 日韩在线小视频| 精品人伦一区二区三区蜜桃网站| 日韩欧美中文免费| 大桥未久av一区二区三区| 亚洲成人教育av| 亚洲女人天堂色在线7777| 日韩免费在线观看视频| 亚洲理论在线a中文字幕| 欧美国产欧美亚洲国产日韩mv天天看完整| 亚洲性线免费观看视频成熟| 国产精品久久久久久久久久东京| 欧美成人免费全部| 久久色精品视频| 亚洲欧美激情精品一区二区| 久久影院资源站| 色悠久久久久综合先锋影音下载| 久久影院中文字幕| 日韩欧美中文字幕在线播放| 国产精品18久久久久久首页狼| 国产一区二区激情| 亚洲精品国产品国语在线| 亚洲在线第一页| 亚洲欧美国产精品| 欧美不卡视频一区发布| 欧美大片免费观看| 国产精品18久久久久久首页狼| 中文.日本.精品| 国产成人亚洲综合91| 日本精品va在线观看| 国产一区av在线| 九九久久综合网站| 日韩精品视频免费专区在线播放| 海角国产乱辈乱精品视频| 亚洲的天堂在线中文字幕| 91精品久久久久久久久久久| 国产精品高清在线观看| 亚洲老头老太hd| 精品国产91久久久久久| 日韩黄色在线免费观看| 午夜精品久久久久久久久久久久久| 国产精品第七十二页| www.日韩系列| 欧美精品久久久久久久久久| 奇米一区二区三区四区久久| 欧美影院在线播放| 亚洲精品第一国产综合精品| 欧美性猛交xxxx| 青青在线视频一区二区三区| 国产亚洲视频中文字幕视频| 久久精视频免费在线久久完整在线看| 国产精品自拍小视频| 国产精品久久久久久av福利| 一本色道久久综合狠狠躁篇的优点| 91精品国产综合久久久久久蜜臀| 国产高清在线不卡| 成人免费福利视频| 亚洲人成在线一二| 亚洲区中文字幕| 欧美日韩一区二区免费在线观看| 国产精品18久久久久久首页狼| 国内成人精品一区| 欧美激情乱人伦一区| 国产999在线观看| 亚洲第一精品夜夜躁人人爽| 亚洲欧美国产精品久久久久久久| 国产精品看片资源| 欧美大片第1页| 欧美日韩国产91| 欧美伦理91i| 亚洲精品日韩久久久| 日韩美女视频中文字幕| 一区二区欧美激情| 久久久久久久网站| 亚洲国产精品久久精品怡红院| 在线视频欧美性高潮| 国产69精品99久久久久久宅男| 中文字幕日韩欧美精品在线观看| 日韩中文在线观看| 亚洲美女av在线| 中文字幕日本欧美| 欧美孕妇孕交黑巨大网站| 性色av一区二区三区| 国产精品成人久久久久| 伊人久久免费视频| 亚洲欧美中文在线视频| 亚洲高清久久久久久| 中文字幕av一区中文字幕天堂| 亚洲精品videossex少妇| 国产啪精品视频网站| 91精品国产综合久久香蕉的用户体验| 国产精品对白刺激| 欧美影院成年免费版| 亚洲日韩中文字幕| 久久久女人电视剧免费播放下载| 在线视频中文亚洲| 26uuu亚洲国产精品| 精品美女永久免费视频| 91久久精品视频| 日韩视频免费大全中文字幕| 欧美激情国内偷拍| 亚洲性69xxxbbb| 中文字幕欧美日韩精品| 欧美中文在线观看国产| 国产成人精品视频| 亚洲人成毛片在线播放| 成人激情在线观看| 亚洲伦理中文字幕| 欧美国产视频一区二区| 国产精品ⅴa在线观看h| 宅男66日本亚洲欧美视频| 亚洲欧美日韩中文在线制服| 亚洲自拍偷拍一区| 精品久久久久久久久久久| 成人免费黄色网| 日韩成人在线视频| 粗暴蹂躏中文一区二区三区| 欧美成人一区二区三区电影| 亚洲精品www| 91精品国产成人| 亚洲影视中文字幕| 欧美国产日韩二区| 国产成人精品午夜| 欧美又大又粗又长| 日本一本a高清免费不卡| 久久好看免费视频| 国产精品人成电影在线观看| 亚洲视频在线观看免费| 久久成人精品电影| 国产欧美日韩中文字幕在线| 国产日韩欧美在线| 亚洲午夜av电影| 国产精品偷伦视频免费观看国产| 国产精品尤物福利片在线观看| 成人免费在线网址| 亚洲精品www久久久久久广东| 成人信息集中地欧美| 亚洲国产美女精品久久久久∴| 日韩视频永久免费观看| 97国产精品久久| 欧美肥臀大乳一区二区免费视频| 91成人精品网站| 精品小视频在线| 亚洲精选一区二区| 亚洲色图欧美制服丝袜另类第一页| 欧美在线激情网| 青青精品视频播放|