Java集合框架(一)-ArrayList

化羽羽發表於2022-06-19

大佬理解->Java集合之ArrayList

1、ArrayList的特點

存放的元素有序
元素不唯一(可以重複)
隨機訪問
插入刪除元素
非執行緒安全

2、底層實現

底層初始化,使用一個Object型別的空物件陣列,初始長度為0;

原始碼

//Object型別物件陣列引用
transient Object[] elementData;
//預設空的Object陣列
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//例項化時,將Object型別物件陣列引用 指向 預設空的Object陣列
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

首次新增元素,自動進行擴容,預設擴充容量是10(陣列的長度,也就是集合存放元素的個數);

原始碼

//如果是第一次新增元素
public boolean add(E e) {
    //private int size; //size = 0;
    //呼叫ensureCapacityInternal(int minCapacity)方法
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

//minCapacity = 1;
private void ensureCapacityInternal(int minCapacity) {
    //呼叫calculateCapacity(Object[] elementData, int minCapacity)方法
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    //判斷是不是預設空的Object陣列
    //如果是進入選擇一個陣列容量
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //private static final int DEFAULT_CAPACITY = 10;
        //minCapacity = 1;
        //所以第一次新增元素時,自動進行擴容,預設擴充容量是10
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

3、擴容

//當前一次擴容的陣列容量不足時(放滿10個元素,再想新增一個元素,容量不足),開始進行動態擴容;
//每次擴容,是之前一次擴容後的陣列容量的1.5倍(即:每次都在前一次陣列容量的基礎上,增加一半-右移1位);
//最大容量Integer.MAX_VALUE - 8,即2^31-8
//擴容方法
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length; //舊陣列的容量
    int newCapacity = oldCapacity + (oldCapacity >> 1); //新陣列的容量 = 老陣列的容量+老陣列的一半(右移一位)
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0) //如果新陣列的容量大於最大值,將陣列的容量設定為Integer.MAX_VALUE - 8
        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) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    //private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
    MAX_ARRAY_SIZE;
}

4、ArrayList初始化

基於多型建立ArrayList集合物件

List<Object> list = new ArrayList<>(); // 推薦
Collection collection = new ArrayList();
ArrayList arrayList = new ArrayList();
List<Integer> intList = new ArrayList<>(); //可以使用泛型,指定存放資料的型別

5、常用方法

方法 說明
add(Object obj) 新增元素
add(int index, E element) 指定下標新增元素
remove(int index) 移除元素
get(int index)) 獲取元素
size() 集合元素個數
contains(Object o) 是否包含某元素
isEmpty() 集合是否為空

5.1 add(Object obj)

//新增元素方法:add(Object obj),每次新增元素都是自動新增到陣列的末尾,元素下標值從0開始,跟陣列一致;
//可以新增重複值;
//可以新增null值;

5.2 add(int index, E element)

//指定下標新增元素和刪除元素,執行效率比較低;

5.3 remove(int index)

// 根據下標刪除,如果重複,只能刪除第一個出現的;

5.4 get(int index))

// 獲取元素方法:get(下標值),只能通過下標取值;
//當訪問下標值超出了集合元素的最大下標值,報下標越界異常:java.lang.IndexOutOfBoundsException
// 可用的下標值的範圍:最小值是0,最大值是集合元素的個數 - 1

5.5 size()

// 獲取集合中元素個數方法:size();

5.6 contains(Object o)

// 判斷list集合中,是否包含某個元素方法:contains(查詢元素值),返回true,代表存在,返回false,代表不存在;

5.7 isEmpty()

// 判斷list集合是否為空方法:isEmpty(),返回true代表沒有元素,空的,返回false,代表有元素,不是空的
// 底層就是通過集合中元素個數size == 0 判斷,所以也可以使用size() == 0判斷集合非空

原始碼

public boolean isEmpty() {
    return size == 0;
}

5.8 clear()

//清空list集合方法:clear(),清除集合中的所有元素

原始碼

ublic void clear() {
    modCount++;

    // clear to let GC do its work
    for (int i = 0; i < size; i++) //一次將陣列賦值為null;
    elementData[i] = null;

    size = 0; //設定陣列長度為0;
}

5.9 toArray()

// list集合一步轉換為陣列方法:toArray(),返回的是Object型別陣列

6、陣列轉換成集合

Arrays.asList(目標陣列)

String[] strArrays = {"奧迪", "賓士", "寶馬"};
List<String> strList1 = Arrays.asList(strArrays);
System.out.println(strList1); //[奧迪, 賓士, 寶馬]

7、遍歷

List<String> strList = new ArrayList<>();
strList.add("Audi");
strList.add("Benz");
strList.add("Bmw");
strList.add("Audi");

//for迴圈
for (int i = 0; i < strList.size(); i++) {
    System.out.println("汽車品牌:" + strList.get(i));
}

//迭代器
//Iterator迭代器,只能通過集合獲取,不可以重複使用,迭代結束,迭代器就失效,如果想再次使用,需要重新獲取
Iterator<String> iterator = strList.iterator();
// 迭代器遍歷,使用while,不知道其中元素個數
while(iterator.hasNext()){
    System.out.println("汽車品牌:" + iterator.next());
}

執行結果:

汽車品牌:Audi
汽車品牌:Benz
汽車品牌:Bmw
汽車品牌:Audi

8、Vector(執行緒安全)

//Vector,底層資料結構是和ArrayList一致的,都是物件陣列,但是它的操作是執行緒安全的,每個方法都帶有synchronized同步;
// 預設初始容量是10,可以自定義,但是不能小於0,預設每次擴容是前一次容量的一倍,擴容的數量也是可以指定的,如果指定,每次都是在前一次基礎上擴容指定的數量

相關文章