java語言基礎--集合學習,ArrayList和Linkedlist
阿新 • • 發佈:2018-10-21
rem 超出 pri internal mac extend pre 所有 因此
Collection<E>接口
這個接口是集合框架最頂級的接口,該接口擴展了Iterable接口,這意味著所有的集合類fore-each風格進行遍歷。
ArrayList 與 Linkedlist
區別:
ArrayList是實現了基於動態數組,LinkedList基於鏈表。對於隨機訪問get和set,ArrayList性能要優於LinkedList,因為LinkedList要移動指針。對於刪除和新增LinkedList性能要優於ArrayList,因為ArrayList要移動數據。
ArrayList的擴容方式,擴容時機
當集合中的元素超出容量,便會進行擴容操作。擴容操作也是ArrayList 的一個性能消耗比較大的地方,所以若我們可以提前預知數據的規模,應該通過public ArrayList(int initialCapacity) {}構造方法,指定集合的大小,去構建ArrayList實例,以減少擴容次數,提高效率
ArrayList的成員屬性
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ private static final long serialVersionUID = 8683452581122892189L; //默認初始容量 private static final int DEFAULT_CAPACITY = 10; //默認構造函數的空數組 privatestatic final Object[] EMPTY_ELEMENTDATA = {}; //瞬態(在采用Java默認的序列化機制的時候,被該關鍵字修飾的屬性不會被序列化)的數組,真正存放元素的數組 transient Object[] elementData; // non-private to simplify nested class access //elementData存放元素的數量,這裏和容量不一樣 private int size; }
ArrayList的構造方法
public ArrayList(int initialCapacity) { super();//即父類protected AbstractList() {} if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity];//創建一個容量為initialCapacity的空的(但是size==0)對象數組 } public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA;//將空數組賦值給elementData } public ArrayList(Collection<? extends E> c) { //調用Collection.toArray()方法得到一個對象數組,並賦值給elementData elementData = c.toArray(); //設置size的值 size = elementData.length; //c.toArray()如果沒有返回Object[]時,利用Arrays.copyOf 來復制集合c中的元素到elementData數組中 if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); }
add方法
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e;//將數組元素追加到末尾,並修改size return true; } private void ensureCapacityInternal(int minCapacity) { //根據EMPTY_ELEMENTDATA 判斷數組是否是用默認構造函數初始化的,(這裏不考慮ArrayList(Collection<? extends E> c)這種情況是因為,minCapacity是肯定大於c的size的) if (elementData == EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++;///如果確定要擴容,會修改modCount // 如果傳入的數大於數組原容量 則開始擴容 if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // int oldCapacity = elementData.length; //擴容為原來的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); //取1.5倍的容量和傳入的擴容系數的最大值 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0)//這裏的 MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } //最大返回 Integer.MAX_VALUE private static int hugeCapacity(int minCapacity) { // overflow if (minCapacity < 0) throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE; }
指定位置插入add(int index, E element)
public void add(int index, E element) { rangeCheckForAdd(index);//範圍檢查 ensureCapacityInternal(size + 1); // Increments modCount!! //將index開始的數據 向後移動一位 System.arraycopy(elementData, index, elementData, index + 1,size - index); elementData[index] = element; size++; } private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
addAl方法
public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; //擴容準備 ensureCapacityInternal(size + numNew); // 復制數組 ,並載入數據 System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; }
查詢
public E get(int index) { rangeCheck(index);//範圍檢查 return elementData(index);//下標獲取數據 } @SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; }
Linkedlist
transient int size = 0;//集合元素數量 transient Node<E> first; //頭部節點 transient Node<E> last;//尾部節點
構造方法
public LinkedList() {} public LinkedList(Collection<? extends E> c) { this(); addAll(c);//將集合c所有元素插入鏈表中 }
內部類 Node
//雙向鏈表 private static class Node<E> { E item;//元素值 Node<E> next;//前節點引用 Node<E> prev; //後節點引用 Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
add方法
//尾部插入新節點 public boolean add(E e) { linkLast(e); return true; } void linkLast(E e) { final Node<E> l = last;//記錄原來的尾部節點 final Node<E> newNode = new Node<>(l, e, null);//以原尾部節點為前節點生成新節點 last = newNode;//將當期節點設置為尾部節點 if (l == null)//如果原尾部節點為null 則將當前節點設置為鏈表的首節點 first = newNode; else//否則將當前節點設置為原尾部節點的後節點 l.next = newNode; size++; modCount++; }
其他例子就不看了,總得來說 LinkedList 修改數據時,只需要設置新節點和關聯前後節點關系即可,不向ArrayList那樣,增加一個數據。後面的數據都要後移。因此LinkedList 對數據操作效率高。
java語言基礎--集合學習,ArrayList和Linkedlist