數據結構之線性表之ArrayList源碼學習

好久沒寫博客,一直是寫在筆記上面。

我一直用的JDK8,所以今天的源碼分析也是基於JDK8。

 

ArrayList簡介

 

ArrayList 是一個動態數組隊列。與Java中的數組相比,它的容量能動態增長。它繼承於AbstractList,實現了List, RandomAccess, Cloneable, java.io.Serializable這些接口。

 

 


ArrayList 的爸爸是AbstractList,實現了List。AbstractList 提供了相關的添加、刪除、修改、遍歷等功能。


ArrayList 實現了RandmoAccess接口,支持快速隨機訪問。
ArrayList 實現了Cloneable接口,即覆蓋了函數clone(),能被克隆。
ArrayList 實現java.io.Serializable接口,這意味着ArrayList支持序列化,能通過序列化去傳輸。

和Vector不同,ArrayList中的操作不是線程安全的!所以,建議在單線程中才使用ArrayList,而在多線程中可以選擇Vector或者CopyOnWriteArrayList。

 

ArrayList的屬性

  1. 序列化id
  2. 默認初始的容量
  3. 數組長度

  4. .........

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
	// 序列化id
	private static final long serialVersionUID = 8683452581122892189L;
	// 初始的容量(這裏和Android Java不一樣,Android是12)
	private static final int DEFAULT_CAPACITY = 10;
	// 一個空對象
	private static final Object[] EMPTY_ELEMENTDATA = new Object[0];
	// 一個空對象,如果使用默認構造函數創建,則默認對象內容默認是該值
	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new Object[0];
	// 當前數據對象存放地方,當前對象不參與序列化
	transient Object[] elementData;
	// 當前數組長度
	private int size;
	// 數組最大長度
	private static final int MAX_ARRAY_SIZE = 2147483639;
 
	
}

ArrayList構造函數

 

  • 默認構造函數

 

 public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

//當進行第一次add的時候,elementData將會變成默認的增量長度:10.
  • int類型參數構造函數

 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);
        }
    }
  • Collection類型的參數構造函數

public ArrayList(Collection<? extends E> c) {

      //將collection對象轉換成數組,然後將數組的地址的賦給elementData。
        elementData = c.toArray();
      
        //如果它的長度不爲0,進而判斷它是否爲Object類型的數組,如果不是的話,給它copyOf()爲一個Object類型的數組。否則,給它置空。

        if ((size = elementData.length) != 0) {
          
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

ArrayList的方法

 

插入數據:add()方法

 

add方法:

  1. 確保數組已使用長度(size)加1之後的容量足夠保存下一個數據
  2. 修改次數modCount 標識自增1,如果當前數組已使用長度(size)加1後的大於當前的數組長度,則調用grow方法,增長數組,grow方法會將當前數組的長度變爲原來容量的1.5倍。
  3. 確保新增的數據有地方存儲之後,則將新元素添加到位於size的位置上。
  4. 返回添加成功布爾值。

指定位置插入數據:add(int index, E element)方法

 

 

 

在指定位置添加元素:首先rangeCheckForAdd(index)判斷索引是否超出數組下標,之後檢測是否需要擴容,使用System.arraycopy 將需要插入的位置(index)後面的元素統統往後移動一位。將新的數據內容存放到數組的指定位置(index)上。

 

 

get方法:返回指定位置上的元素

 

 

 

set方法:更改指定位置的元素,並且返回舊元素

 

contains方法:調用indexOf方法,遍歷數組中的每一個元素作對比,如果找到對於的元素,則返回true,沒有找到則返回false。

 

 

remove方法:有兩個,(1)根據索引移除元素;(2)根據對象移除元素

 

根據索引remove

 

索引沒有越界時,操作數++,將指定位置(index)上的元素都往前移動一位,將最後面的一個元素置空,好讓垃圾回收器回收,並且將原來的值oldValue返回

 

根據對象remove

 

 

循環遍歷所有對象,得到對象所在索引位置,然後調用fastRemove方法,執行remove操作

 

clear方法:數組內的元素都置空,不減小數組容量。

 

 

 

trimToSize方法:將elementData的數組設置爲ArrayList實際的容量,動態增長的多餘容量被刪除

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章