JavaSE基礎知識學習-----集合之ArrayList

ArrayList

首先明確的是:Collection的子接口是List接口,Listc存儲的是有序可重複的元素,ArrayList是List接口的主要實現類,List接口的主要實現類有:

1.ArrayList

由數組方式實現數據存儲,固然數組的訪問速度比鏈表快。源碼以下:java

public class ArrayList<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;

/**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer.
 */
private transient Object[] elementData;
複製代碼

2.LinkedList

由鏈接實現數據的存儲,隨機添加和刪除元素的的操做的效率要高於數組,簡單說就更適用於頻繁的插入和實現操做。數組

3.Vector

是一種古老的實現類,在Vector類中,裏面的方法添加了synchronized修飾,是線程安全的,關於線程的相關知識會在後續的學習中,他的性能比ArrayList差,用的地方比較少,安全

ArrayList經常使用方法

ArrayList經常使用的方法和Collection基本同樣,也大體看看吧,就當複習吧。dom

1.add("AA");向集合中添加一個元素
public static void main(String[] args) {
	List<String> list = new ArrayList<String>();
	list.add("AA");
}
複製代碼
2.add(2, "CC");將指定的元素插入此列表中的指定位置。索引從0開始
public static void main(String[] args) {
	List<String> list = new ArrayList<String>();
	list.add("AA");
	list.add("BB");
	list.add("DD");
	System.out.println(list);
	list.add(2, "CC");
	System.out.println(list);
}
複製代碼

結果爲:性能

[AA, BB, DD]
[AA, BB, CC, DD]
複製代碼
3.addAll(list2);將形參中的集合元素所有添加到當前集合中的尾部。
public static void main(String[] args) {
	List<String> list = new ArrayList<String>();
	list.add("AA");
	list.add("BB");
	list.add("DD");
	List<String> list2 = new ArrayList<String>();
	list2.add("CC");
	list2.add("EE");
	list.addAll(list2);
	System.out.println(list);
}
複製代碼

結果爲:學習

[AA, BB, DD, CC, EE]
複製代碼
4.addAll(2, list2);將形參中集合元素添加到當前集合指定的位置。
public static void main(String[] args) {
	List<String> list = new ArrayList<String>();
	list.add("AA");
	list.add("BB");
	list.add("DD");
	List<String> list2 = new ArrayList<String>();
	list2.add("CC");
	list2.add("EE");
	list.addAll(2, list2);
	System.out.println(list);
}
複製代碼

結果爲:this

[AA, BB, CC, EE, DD]
複製代碼
5.clear();清空當前集合中全部元素
list.clear();
複製代碼

注意:如下方法和Collection同樣,都依賴元素對象的equals方法。更多的時候都須要重寫equals方法。

6.contains("aa");返回當前 元素是否包含某一個對象。當前放回false。
public static void main(String[] args) {
	List<String> list = new ArrayList<String>();
	list.add("AA");
	list.add("BB");
	list.add("DD");
	boolean contains = list.contains("aa");
	System.out.println(contains);
}
複製代碼
7.get(1);獲取當前集合中指定位置的元素,這裏返回BB
public static void main(String[] args) {
	List<String> list = new ArrayList<String>();
	list.add("AA");
	list.add("BB");
	list.add("DD");
	String string = list.get(1);
	System.out.println(string);
}
複製代碼
8.indexOf("BB");返回當前集合中首次出現形參對象的位置,若是集合中不存在就返回-1.
public static void main(String[] args) {
	List<String> list = new ArrayList<String>();
	list.add("AA");
	list.add("BB");
	list.add("BB");
	int indexOf = list.indexOf("BB");
	System.out.println(indexOf);
}
複製代碼

簡單的方法就查詢jdkAPI文檔吧,下面作簡要的說明:

1.size();放回當前集合元素個數.
2.isEmpty();判斷集合是否爲空,返回布爾類型的結果。
3.lastIndexOf(Object o);返回集合中最後一次出現形參元素的索引,不存在就返回-1。
4.toArray();將集合轉換爲數組
5.set(int index,E element);用指定元素替代集合中指定位置的元素。
6.remove(Object o);移除集合中首次出現的元素。
7.remove(int index);移除集合中指定位置的元素。

ArrayList實現原理(源碼解讀)

ArrayList是List接口的可變數組的實現,容許包括null在內的全部元素,既然是數組,那麼該類確定會存在改變存儲列表的數組大小的方法。 每個ArrayList實例都有一個容量,該容量是用來存儲列表元素的數組的大小,他老是等於列表的大小,隨着往ArrayList中添加元素,這個容量也會相應的總動增加,自動增加就會帶來數據向新數組的從新拷貝。spa

1.底層使用數組實現

private transient Object[] elementData;
複製代碼

2.構造方法以下:

public ArrayList() {
    this(10);
}
 public ArrayList(int initialCapacity) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    this.elementData = new Object[initialCapacity];
}
 public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
}
複製代碼

在初始化ArrayList實例時,能夠構造一個初始容量爲10的空列表,也能夠構造一個指定初始容量的空列表以及構造一個包含指定Collection元素的列表。線程

3.如何實現存儲的?

3.1使用set(int index, E element) ;方法,用指定的元素替代指定位置的元素
public E set(int index, E element) {
    rangeCheck(index);

    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}
複製代碼
3.2add(E e);將指定的元素添加到集合尾部
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
複製代碼
3.3add(int index, E element)將指定的元素插入此列表中的指定位置
public void add(int index, E element) {  
    if (index > size || index < 0)  
        throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);  
    // 若是數組長度不足,將進行擴容。  
    ensureCapacity(size+1);  // Increments modCount!!  
    // 將 elementData中從Index位置開始、長度爲size-index的元素,  
    // 拷貝到從下標爲index+1位置開始的新的elementData數組中。  
    // 即將當前位於該位置的元素以及全部後續元素右移一個位置。  
    System.arraycopy(elementData, index, elementData, index + 1, size - index);  
    elementData[index] = element;  
    size++;  
}  
複製代碼

4.如何讀取元素?

public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}
複製代碼

5.刪除元素

public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}
複製代碼

注意:從集合中移除一個元素,若是這個元素不是最後一個元素,那麼這個元素的後面元素會想向左移動一位。code

5.如何實現擴容的?

public void ensureCapacity(int minCapacity) {
    if (minCapacity > 0)
        ensureCapacityInternal(minCapacity);
}
 private void ensureCapacityInternal(int minCapacity) {
    modCount++;
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}
 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)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}
複製代碼

從上面的代碼能夠看出,數組進行擴容時,會將老數組的全部元素拷貝到新數組中, 其中新數組的大小是老數組大小右移一位再加上老數組的大小。

6.手動調整底層數組的容量爲列表實際元素大小的方法

public void trimToSize() {
    modCount++;
    int oldCapacity = elementData.length;
    if (size < oldCapacity) {
        elementData = Arrays.copyOf(elementData, size);
    }
}
複製代碼
相關文章
相關標籤/搜索