­

Java集合框架(一)-ArrayList

大佬理解->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 = {"奧迪", "Benz", "寶馬"};
List<String> strList1 = Arrays.asList(strArrays);
System.out.println(strList1); //[奧迪, Benz, 寶馬]

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,默認每次擴容是前一次容量的一倍,擴容的數量也是可以指定的,如果指定,每次都是在前一次基礎上擴容指定的數量