arraylist,linklist的部分源碼介紹和一些區別
阿新 • • 發佈:2018-05-19
copy 因此 else list GC prev RF iou 返回
arraylist:
3個構造器:
(1)默認構造器(使用這個構造器初始化的集合容量為默認初始化容量10)
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
(2)自定義容量的構造器(如果初始化是傳入的列表初始容量>0則正常創建傳入的容量的集合,如果傳入的列表初始容量為0,則創建一個用於空實例的共享數組實例,其他情況時拋出異常)
private static final int DEFAULT_CAPACITY = 10;// 默認初始化容量
private static final Object[] EMPTY_ELEMENTDATA = {};//用於空實例的共享空數組實例。
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); } }
(3)傳入一個集合作為參數的構造器(傳入的集合轉為數組,如果數組的長度!=0,並且數據的類的類對象不是Object類對象則調用Arrays.copyOf()方法初始化,如果數組長度為0 則創建一個空實例)
public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
方法
1 add方法(先檢查容量是否足夠,如果不夠則擴容,如果容量足夠就把要加入的數據放在原來數據的末尾,並且加容量+1)
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
每次擴容後容量為之前的1.5倍,再將數據復制到新擴容的集合裏
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); }
2 get 方法 (先進行範圍檢查,如果所查的索引不再集合的容量區間裏則拋出越界異常,如果所查索引沒有超出範圍,則正常返回所查索引對應的值)
public E get(int index) { rangeCheck(index); return elementData(index); } private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
3 remove 方法
(如果remove的參數是一個對象 則先判定這個對象是否==null,如果為空則找到值為空的索引,在根據下面介紹的fastRemove(int index)方法將其刪除,如果傳入的對象不為空,則先找到所刪除的值在集合中的下標,在用fastRemove(int index)方法將其刪除
如果remove的參數是一個索引值,則先判定索引值是否在集合的容量區間內,再求得要移動的次數,然後刪除該元素
)
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; } public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work return oldValue; }
根據索引將集合中的元素刪除,首先求得刪除該元素需要移動的次數,如果移動的次數>0則調用arraycopy()方法獲得新的集合,將原始的集合的最後一項置為空
private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }
linklist
構造器
1 默認構造器(無參數)
public LinkedList() { }
2 傳入一個集合的構造器
public LinkedList(Collection<? extends E> c) { this(); addAll(c); }
方法
1 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) first = newNode; else l.next = newNode; size++; modCount++; }
2 remove方法(將要刪除的節點的前一個節點指向要刪除的節點的下一個節點即可實現節點的刪除)
public boolean remove(Object o) { if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); return true; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; } E unlink(Node<E> x) { // assert x != null; final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev; if (prev == null) { first = next; } else { prev.next = next; x.prev = null; } if (next == null) { last = prev; } else { next.prev = prev; x.next = null; } x.item = null; size--; modCount++; return element; }
ArrayList與LinkedList的區別
ArrayList基於數組實現,因此具有: 有序、元素可重復、插入慢、 索引快 這些數組的特性; (查詢快,增刪慢)
LinkedList 基於雙向鏈表實現, 因此具有鏈表 插入快、 索引慢的特性;(增刪快,查詢慢)
arraylist,linklist的部分源碼介紹和一些區別