麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

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

ArrayList用法詳解與源碼分析

2019-11-14 21:50:01
字體:
來源:轉載
供稿:網友
ArrayList用法詳解與源碼分析說明

此文章分兩部分,1.ArrayList用法。2.源碼分析。先用法后分析是為了以后忘了查閱起來方便~~

ArrayList 基本用法

1.創建ArrayList對象

//創建默認容量的數組列表(默認為10)ArrayList<E> a = new ArrayList<E>();//創建容量為initialCapacity的數組列表ArrayList<E> a = new ArrayList<E>(int initialCapacity);//用一個集合來初始化數值列表ArrayList<E> a = new ArrayList<E>(Collection<? extends E> c);  
Mark:

CapacitySize 時兩個不同的概念:Size: ArrayList包含的元素個數。capacity : ArrayList的容量(默認為10)。它是一個大于或等于size的值。當它的值小于size是就會對ArrayList進行擴容實現可變長數組。簡單來說,capacity就是為了實現可變長數組而設計的。 (具體分析請看下面的源碼分析)

2.ArrayList方法

向ArrayList添加元素
/***********a是上面創建的ArrayList對象***************///添加一個元素a.add(E e);//在特定的位置添加元素,index后面的元素全部向后移一位a.add(int index, E e);//在ArrayList 后面 添加集合a.addAll(Collection<? extends E> c);//從特定的位置添加集合a.addAll(int index, Collection<? extends E> c);  
獲取ArrayList的元素
//獲取特定索引的元素a.get(int index);  
Mark:

遍歷ArrayList: 一般使用for-eachfor(E e : a)dosomething;用for-each的主要優勢:相對傳統的for循環,for-each更簡潔,不容易出錯,而且沒有性能的損失

修改(更新)ArrayList的元素
//用e替換換index位置的元素a.set(int index, E e);
Mark:

注意: 區分set與add的用法add 是添加一個新的元素,要開辟新的空間來保存元素set 是修改特定位置的元素,index位置必須要已經存在元素,否則會越界

刪除ArrayList的元素
//刪除索引為index的元素,后面的元素全都向前移一位a.remove(int index);/*刪除在列表中和obj相等的第一個元素(首次出現),  * 就做動作,保持列表原來的狀態* 比如:a [1, 3, 7, 5, 7],執行a.remove((Integer)7)后* 結果為:[1, 3, 5, 7]*/a.remove(Object obj);//刪除與集合c中元素相等的元素a.removeAll(Collection<?> c);//保留與集合c中元素相等的元素,然后把其他元素刪除(與removeAll相反)a.retainAll(Collection<?> c);  //刪除ArrayList的所有元素,沒有removeAll();方法a.clear();
ArrayList的其他一些比較常用的方法
//獲取ArrayList的元素個數a.size();//判斷ArrayList是否包含某個元素a.contains(Object o)//判斷ArrayList是否是空列表([]),是就返回truea.isEmpty();//獲取ArrayList的子列表,(字串包含索引為fromIndex的元素,不包含toIndex元素)a.subList(int fromIndex, int toIndex);//返回ArrayList的基本數組形式a.toArray();/**ArrayList克隆,調用方法后,會返回a的一份復制。它與普通的復制(=)不同 *賦值后,兩個引用指向同一個對象,會相互影響  *從ArrayList源碼可知,是開辟新的空間來新建一個對象,再把數據復制到新建的對象。*所以,clone后會形成兩個不同的對象,因此不會相互影響。*/a.clone();
Mark:

a.remove(Object obj): 如果a是Integer的泛型列表在支持remove對象時要強制轉換為Ingeger或者Object類型(參考上面例子),如果直接執行a.remove(7),就會調用 a.remove(int index)方法。


ArrayList源碼分析首先,看看ArrayList定義的屬性
PRivate static final int DEFAULT_CAPACITY = 10;  private static final Object[] EMPTY_ELEMENTDATA = {};  transient Object[] elementData;   private int size;    

DEFAULT_CAPACITY就是上面提到的默認容量大小,從屬性定義可知,容量的默認大小為10。

EMPTY_ELEMENTDATA一個空的數組對象,主要用來與elementData做比較,elementData是否為空

elementData最核心的一個屬性。它是ArrayList的廬山真面目,ArrayList之所以是可變長的,主要是ArrayList內部有elementData這個東東在搞鬼~~。 ArrayList可變長原理:當size大于capacity時,ArrayList就會調用擴容函數新建一個容量更大的elementData數組來代替原來的數組來實現擴容。總的來說,ArrayList的可變長功能主要時圍繞著capacity與elementData來實現的

實現可變長數組的主要方法:

public void ensureCapacityInternal(int minCapacity)private void ensureExplicitCapacity(int minCapacity)private void grow(int minCapacity) //核心方法

ensureCapacityInternal解析

/** * 此函數大概就叫內部容量確定函數,主要是在每次添加元素這些增大size的 * 動作里調用,用來判斷需不需要增加capacity大小實現動態分配 */  private void ensureCapacityInternal(int minCapacity) {   /**    *這個判斷只要是針對使用new ArrayList<E>()構造對象設定,以免頻繁的擴容。    *如果if判斷為真,那么就是使用new ArrayList<E>()構造對象的.      *此刻就要選一個最大的容量作為期待的最小容量,避免頻繁擴容    *詳細解析看下面的例子!!    */    if (elementData == EMPTY_ELEMENTDATA) {        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);    }    //調用最終確認方法,需不需要擴容由此方法決定    ensureExplicitCapacity(minCapacity);}  
if (elementData == EMPTY_ELEMENTDATA)作用解析

首先,我們新建一個類(我的為MyList),把ArrayList的源碼復制過來方便為所欲為~~,然后把一些報錯除去。最后我們修改下代碼:

// 把ensureCapacityInternal的if語句注釋掉,/*if (elementData == EMPTY_ELEMENTDATA) {        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);    }*/  在**grow**方法里添加一個輸出語句     System.out.println("-----invoke grow()------------");

寫我們的測試類:

  public class Test {public static void main(String[] args) {     MyList<Integer> i = new MyList<Integer>();     MyList<Integer> i2 = new MyList<Integer>(10);    System.out.println("------使用new MyList<Integer>()------ ");    i.add(1);    i.add(1);    i.add(1);    i.add(1);    System.out.println("------使用new MyList<Integer>(10)------ ");    i2.add(1);    i2.add(1);    i2.add(1);    i2.add(1);}

}輸出:

———使用new MyList()—————-invoke grow()————————-invoke grow()————————-invoke grow()————————-invoke grow()—————————使用new MyList(10)———

可以看出,如果不是使用if判斷,使用new ArrayList()方法每次添加元素都會調用grow,而每次調用grow都會生成一個新的數組。所以為了效率內存考慮要添加if判斷。

ensureExplicitCapacity方法

/** *此代碼功能很簡單,只是進行一個簡單的判斷,看是否需要擴容 *如果需要的容量比實際的容量大就進行擴容 */private void ensureExplicitCapacity(int minCapacity) {    modCount++;    if (minCapacity - elementData.length > 0)        grow(minCapacity);}

grow(核心方法)

 /**  *擴容的具體動作  */ private void grow(int minCapacity) {    int oldCapacity = elementData.length;    //定義擴容后的容量大小為原來容量的3/2    int newCapacity = oldCapacity + (oldCapacity >> 1);    //如果擴容后的容量還是比期待的容量小,那么使用minCapacity為擴容后的容量    if (newCapacity - minCapacity < 0)        newCapacity = minCapacity;    if (newCapacity - MAX_ARRAY_SIZE > 0)        newCapacity = hugeCapacity(minCapacity);    /*這里實現了動態數組的特性。     *跟蹤copyOf源碼可以發現,實現方法:新建一個大小為newCapacity數組,     *然后把elementData之前的元素復制到新的數組,     *最后把新數組返回f賦值給elementData以實現動態數組     */    elementData = Arrays.copyOf(elementData, newCapacity);}  
總結:

根據源碼分析,可以知道:

  1. ArrayList本質上是一個數組。只不過是數組上包裝了一層華麗的外套而已。
  2. ArrayList動態數組功能主要思想是,每當數組的空間不夠時,ArrayList會自動把緩沖區(elementData,我們叫他做緩沖區把~~)的數據復制到一個新的緩沖區里,(大小一般為原來的3/2),并令它覆蓋原來的緩沖區成為自己的緩沖區。

常用方法分析

寫到這發現文章太長了,所以決定常用方法就寫幾個算了,不全寫了。常用方法的源碼都很簡單。大多是對elementData這個數組操作返回而已。

add方法
public boolean add(E e) {   //此方法上面已介紹    ensureCapacityInternal(size + 1);      //操作elementData,把e添加到數組里    elementData[size++] = e;    return true;}
set方法
public E set(int index, E element) {    //檢查是否越界,該函數代碼很簡單,就是簡單判斷index與size大小。    rangeCheck(index);    //以下代碼跟add對比下就知道他們的區別    E oldValue = elementData(index);    elementData[index] = element;    return oldValue;}  

總的來說,ArrayList的源碼不算難,主要部分實現動態數組那部分,其他的方法主要還是在操作elementData數組。感覺ArrayList是一個很常用的數據結構,看懂源碼對以后使用ArrayList肯定有不少幫助,而且解了ArrayList用起來也踏實:-D。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 日韩字幕在线观看 | 久久国产精品电影 | 中文字幕欧美一区二区三区 | 欧洲黄色一级视频 | 欧美精品久久久久久久多人混战 | chinese hd xxxx tube| 久久国产成人午夜av浪潮 | 欧美性猛交xxx乱大交3蜜桃 | 免费观看9x视频网站在线观看 | av资源在线| 99精品视频99 | 美女视频黄视大全视频免费网址 | 九一成人 | 国产chinesehd精品91 | 羞羞网站在线看 | 精品国产96亚洲一区二区三区 | 18被视频免费观看视频 | 久久免费看片 | 欧美日韩精品不卡一区二区三区 | 永久在线观看电影 | 欧美成人视 | 国产jjizz一区二区三区视频 | 国产一级爱c视频 | 国产精品久久久久国产精品三级 | 一级片999 | 久久精品视频16 | 国产最新网站 | japan护士性xxxⅹhd | 黄色影院在线看 | 日韩午夜片 | 午夜免费一区 | 免费观看视频在线 | 成年人网站国产 | 欧美成人精品一区二区 | 久久久久国产成人精品亚洲午夜 | 久久毛片 | 性欧美在线视频 | 香蕉视频99| 媚药按摩痉挛w中文字幕 | 媚药按摩痉挛w中文字幕 | 欧美黑人xx|