JDK1.8
ArrayList源碼分析--jdk1.8
LinkedList源碼分析--jdk1.8
HashMap源碼分析--jdk1.8
HashMap概述
1. HashMap是可以動態擴容的數組,基於數組、鏈表、紅黑樹實現的集合。
2. HashMap支持鍵值對取值、克隆、序列化,元素無序,key不可重複value可重複,都可爲null。
3. HashMap初始默認長度16,超出擴容2倍,填充因子0.75f。
4.HashMap當鏈表的長度大於8的且數組大小大於64時,鏈表結構轉變爲紅黑樹結構。
HashMap數據結構
數據結構是集合的精華所在,數據結構往往也限制了集合的作用和側重點,瞭解各種數據結構是我們分析源碼的必經之路。
HashMap的數據結構如下:數組+鏈表+紅黑樹
HashMap源碼分析
/*
* 用數組+鏈表+紅黑樹實現的集合,支持鍵值對查找
*/
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
private static final long serialVersionUID = 362498820763181265L;
/**
* 默認初始容量-必須是2的冪
* 1*2的4次方 默認長度16
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
/**
* 最大容量
* 1*2的30次方 最大容量1073741824
*/
static final int MAXIMUM_CAPACITY = 1 << 30;
/**
* 默認的填充因子 0.75
* 負載因子0.75是對空間和時間效率的一個平衡選擇,建議大家不要修改,除非在時間和空間比較特殊的情況下,
* 如果內存空間很多而又對時間效率要求很高,可以降低負載因子Load factor的值;
* 相反,如果內存空間緊張而對時間效率要求不高,可以增加負載因子loadFactor的值,這個值可以大於1
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/**
* 當桶(bucket)上的節點數大於這個值時會轉成紅黑樹
*/
static final int TREEIFY_THRESHOLD = 8;
/**
* 當桶(bucket)上的節點數小於這個值時樹轉鏈表
*/
static final int UNTREEIFY_THRESHOLD = 6;
/**
* 桶中結構轉化爲紅黑樹對應的table的最小大小
*/
static final int MIN_TREEIFY_CAPACITY = 64;
/**
* Node是單向鏈表,它實現了Map.Entry接口
*/
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
//構造函數Hash值 鍵 值 下一個節點
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
// 實現接口定義的方法,且該方法不可被重寫
// 設值,返回舊值
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
//構造函數Hash值 鍵 值 下一個節點
/*
* 重寫父類Object的equals方法,且該方法不可被自己的子類再重寫
* 判斷相等的依據是,只要是Map.Entry的一個實例,並且鍵鍵、值值都相等就返回True
*/
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
HashMap繼承和實現分析
HashMap extends AbstractMap
AbstractMap extends Object
java中所有類都繼承Object,所以HashMap的繼承結構如上圖。
1. AbstractMap是一個抽象類,實現了Map<K,V>接口,Map<K,V>定義了一些Map(K,V)鍵值對通用方法,而AbstractMap抽象類中可以有抽象方法,還可以有具體的實現方法,AbstractMap實現接口中一些通用的方法,實現了基礎的/get/remove/containsKey/containsValue/keySet方法,HashMap再繼承AbstractMap,拿到通用基礎的方法,然後自己在實現一些自己特有的方法,這樣的好處是:讓代碼更簡潔,繼承結構最底層的類中通用的方法,減少重複代碼,從上往下,從抽象到具體,越來越豐富,可複用。
2.HashMap實現了Map<K,V>、Cloneable、Serializable接口
1)Map<K,V>接口,定義了Map鍵值對通用的方法,1.8中爲了加強接口的能力,使得接口可以存在具體的方法,前提是方法需要被default或static關鍵字所修飾,Map中實現了一些通用方法實現,使接口更加抽象。
2)Cloneable接口,可以使用Object.Clone()方法。
3)Serializable接口,序列化接口,表明該類可以被序列化,什麼是序列化?簡單的說,就是能夠從類變成字節流傳輸,反序列化,就是從字節流變成原來的類
HashMap核心方法分析
1. put方法(3種重載實現)--增
1)V put(K key, V value);//map添加元素
/**
* 新增元素
*/
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
/**
* Implements Map.put and related methods
* @param hash hash for key
* @param key the key
* @param value the value to put
* @param onlyIfAbsent if true, don't change existing value
* onlyIfAbsent默認傳false,覆蓋更改現有值
* @param evict if false, the table is in creation mode.
* @return previous value, or null if none
*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
//如果table爲空 或者 長度爲0
if ((tab = table) == null || (n = tab.length) == 0)
//擴容
n = (tab = resize()).length;
//計算index,並對null做處理
// (n - 1) & hash 確定元素存放在哪個桶中,桶爲空,新生成結點放入桶中(此時,這個結點是放在數組中)
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
// 桶中已經存在元素
else {
Node<K,V> e; K k;
//如果key存在 直接覆蓋 value
// 比較桶中第一個元素(數組中的結點)的hash值相等,key相等
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
// 將第一個元素賦值給e,用e來記錄
e = p;
//如果table[i]是紅黑樹 直接在紅黑樹中插入
// hash值不相等,即key不相等;爲紅黑樹結點
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
//如果是鏈表 則遍歷鏈表
else {
// 在鏈表最末插入結點
for (int binCount = 0; ; ++binCount) {
// 到達鏈表的尾部
if ((e = p.next) == null) {
// 在尾部插入新結點
p.next = newNode(hash, key, value, null);
// 結點數量達到閾值,轉化爲紅黑樹
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
// 跳出循環
break;
}
// 判斷鏈表中結點的key值與插入的元素的key值是否相等
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
// 相等,跳出循環
break;
// 用於遍歷桶中的鏈表,與前面的e = p.next組合,可以遍歷鏈表
p = e;
}
}
// 表示在桶中找到key值、hash值與插入元素相等的結點
if (e != null) { // existing mapping for key
// 記錄e的value
V oldValue = e.value;
// onlyIfAbsent爲false或者舊值爲null
if (!onlyIfAbsent || oldValue == null)
//用新值替換舊值
e.value = value;
// 訪問後回調
afterNodeAccess(e);
// 返回舊值
return oldValue;
}
}
// 結構性修改
++modCount;
// 實際大小大於閾值則擴容
if (++size > threshold)
resize();
// 插入後回調
afterNodeInsertion(evict);
return null;
}
2)putAll(Map<? extends K, ? extends V> m);//添加Map全部元素
/**
* 添加Map全部元素
*/
public void putAll(Map<? extends K, ? extends V> m) {
putMapEntries(m, true);
}
/**
* 判斷下標是否越界
*/
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* src:源數組
* srcPos:源數組要複製的起始位置
* dest:目的數組
* destPos:目的數組放置的起始位置
* length:複製的長度
* 注意:src 和 dest都必須是同類型或者可以進行轉換類型的數組
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
3)addAll(Collection<? extends E> c);//添加Collection類型元素
/**
* 按照指定collection的迭代器所返回的元素順序,將該collection中的所有元素添加到此列表的尾部
*/
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
//將數組a[0,...,numNew-1]複製到數組elementData[size,...,size+numNew-1]
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
4)addAll(int index, Collection<? extends E> c);//指定位置,添加Collection類型元素
/**
* 從指定的位置開始,將指定collection中的所有元素插入到此列表中,新元素的順序爲指定collection的迭代器所返回的元素順序
*/
public boolean addAll(int index, Collection<? extends E> c) {
//判斷下標是否越界
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
//先將數組elementData[index,...,index+numMoved-1]複製到elementData[index+numMoved,...,index+2*numMoved-1]
//即,將源數組中從index位置開始的後numMoved個元素統一後移numNew位
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
總結:
正常情況下會擴容1.5倍,特殊情況下(新擴展數組大小已經達到了最大值)則只取最大值。
2.remove方法(4種重載實現)--刪
1)remove(int index); //根據指定下標 刪除元素
/**
* 根據指定下標 刪除元素
*/
public E remove(int index) {
//判斷索引是否越界
rangeCheck(index);
modCount++;
//獲取舊元素
E oldValue = elementData(index);
//將數組elementData中index位置之後的所有元素向前移一位
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//將原數組最後一個位置置爲null,由GC清理
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
2)remove(Object o); //根據指定元素 刪除元素
/**
* 移除ArrayList中首次出現的指定元素(如果存在),ArrayList中允許存放重複的元素
*/
public boolean remove(Object o) {
// 由於ArrayList中允許存放null,因此下面通過兩種情況來分別處理。
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
//私有的移除方法,跳過index參數的邊界檢查以及不返回任何值
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* 根據下標快速刪除元素
*/
private void fastRemove(int index) {
modCount++;
//將數組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
}
/**
* 清空ArrayList,將全部的元素設爲null,等待垃圾回收將這個給回收掉,所以叫clear
*/
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
3)removeAll(Collection<?> c); //刪除包含在指定容器c中的所有元素
/**
* 刪除ArrayList中包含在指定容器c中的所有元素
*/
public boolean removeAll(Collection<?> c) {
//檢查指定的對象c是否爲空
Objects.requireNonNull(c);
return batchRemove(c, false);
}
/**
* 刪除全部
* @author jiaxiaoxian
* @date 2019年2月12日
*/
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0; //讀寫雙指針
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement) //判斷指定容器c中是否含有elementData[r]元素
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
4)removeIf(Predicate<? super E> filter); //按照一定規則過濾(刪除)集合中的元素
/**
* 按照一定規則過濾(刪除)集合中的元素
* 如:idList.removeIf(id -> id == nul);
* 去掉 List idList 集合中id 爲 null 的
* @param filter
* @return
*/
@Override
public boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
// figure out which elements are to be removed
// any exception thrown from the filter predicate at this stage
// will leave the collection unmodified
int removeCount = 0;
final BitSet removeSet = new BitSet(size);
final int expectedModCount = modCount;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
@SuppressWarnings("unchecked")
final E element = (E) elementData[i];
if (filter.test(element)) {
removeSet.set(i);
removeCount++;
}
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
// shift surviving elements left over the spaces left by removed elements
final boolean anyToRemove = removeCount > 0;
if (anyToRemove) {
final int newSize = size - removeCount;
for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
i = removeSet.nextClearBit(i);
elementData[j] = elementData[i];
}
for (int k=newSize; k < size; k++) {
elementData[k] = null; // Let gc do its work
}
this.size = newSize;
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
return anyToRemove;
}
總結:
remove函數用戶移除指定下標的元素,此時會把指定下標到數組末尾的元素向前移動一個單位,並且會把數組最後一個元素設置爲null,這樣是爲了方便之後將整個數組不被使用時,會被GC,可以作爲小的技巧使用。
3.set方法--改
/**
* 覆蓋指定下標元素
*/
public E set(int index, E element) {
//判斷索引是否越界
rangeCheck(index);
//獲取舊元素
E oldValue = elementData(index);
//覆蓋爲新元素
elementData[index] = element;
//返回舊元素
return oldValue;
}
/**
* 判斷下標是否越界
*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
4.get方法--查
/**
* 返回指定索引的值
*/
public E get(int index) {
//判斷索引是否越界
rangeCheck(index);
return elementData(index);
}
/**
* @author jiaxiaoxian
* @date 2019年2月12日
* 返回下標元素的 值
*/
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
5.indexOf方法--查找下標
/**
* 查找下標, 如果爲null,直接和null比較,返回下標
*/
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
/**
* 查找最後出現的下標,從大往下循環查找
*/
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
6.clone方法--克隆
/**
* 複製,返回此ArrayList 的淺拷貝
*/
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
7.trimToSize方法--刪除冗餘容量
/**
* 判斷數據實際容量大小,刪除自動增長後冗餘的容量
* 該方法用於回收多餘的內存。也就是說一旦我們確定集合不在添加多餘的元素之後,調用 trimToSize() 方法會將實現集合的數組大小剛好調整爲集合元素的大小。
* 注意:該方法會花時間來複制數組元素,所以應該在確定不會添加元素之後在調用
*/
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = Arrays.copyOf(elementData, size);
}
}
8.Itr內部類--類似Iterator,可以幫我們對List進行遍歷,增刪改查等
/**
* 實例化一個Itr對象,並返回
*/
public Iterator<E> iterator() {
return new Itr();
}
/**
* 內部類,類似Iterator,可以幫我們對List進行遍歷,增刪改查等
*/
private class Itr implements Iterator<E> {
int cursor; // index of next element to return 下一個元素
int lastRet = -1; // index of last element returned; -1 if no such 當前元素
int expectedModCount = modCount; //modCount,就是爲了判斷是否有多個線程訪問修改
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
9.ListItr內部類--繼承了內部類Itr,還在此基礎上增加了向前遍歷,增加元素,更改元素內容等功能
/**
* 這個類繼承了內部類Itr
* 除了擁有上一個類的功能,還增加了向前遍歷,增加元素,更改元素內容等功能
*/
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i];
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
10.SubList內部類--基於ArrayList建一個子集類
/**
* 雖然這個類很長,其實裏面的大部分方法調用都是ArrayList中的
* ListIterator在這個類中採用匿名內部類做了一點更改,不過也很類似
* 畢竟這個類就是根據ArrayList建一個子集類,就不贅述了
*/
private class SubList extends AbstractList<E> implements RandomAccess {
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size;
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
public E set(int index, E e) {
// 檢驗索引是否合法
rangeCheck(index);
//實現fail-fast機制 (迭代中不允許操作增刪改)
checkForComodification();
// 舊值
E oldValue = ArrayList.this.elementData(offset + index);
// 賦新值
ArrayList.this.elementData[offset + index] = e;
return oldValue;
}
public E get(int index) {
// 檢驗索引是否合法
rangeCheck(index);
//實現fail-fast機制 (迭代中不允許操作增刪改)
checkForComodification();
return ArrayList.this.elementData(offset + index);
}
public int size() {
checkForComodification();
return this.size;
}
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
parent.add(parentOffset + index, e);
this.modCount = parent.modCount;
this.size++;
}
public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = parent.remove(parentOffset + index);
this.modCount = parent.modCount;
this.size--;
return result;
}
protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
parent.removeRange(parentOffset + fromIndex,
parentOffset + toIndex);
this.modCount = parent.modCount;
this.size -= toIndex - fromIndex;
}
public boolean addAll(Collection<? extends E> c) {
return addAll(this.size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
int cSize = c.size();
if (cSize==0)
return false;
checkForComodification();
parent.addAll(parentOffset + index, c);
this.modCount = parent.modCount;
this.size += cSize;
return true;
}
public Iterator<E> iterator() {
return listIterator();
}
public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
final int offset = this.offset;
return new ListIterator<E>() {
int cursor = index;
int lastRet = -1;
int expectedModCount = ArrayList.this.modCount;
public boolean hasNext() {
return cursor != SubList.this.size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= SubList.this.size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[offset + (lastRet = i)];
}
public boolean hasPrevious() {
return cursor != 0;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[offset + (lastRet = i)];
}
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = SubList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[offset + (i++)]);
}
// update once at end of iteration to reduce heap write traffic
lastRet = cursor = i;
checkForComodification();
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
SubList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.set(offset + lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
SubList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (expectedModCount != ArrayList.this.modCount)
throw new ConcurrentModificationException();
}
};
}
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, offset, fromIndex, toIndex);
}
private void rangeCheck(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private void rangeCheckForAdd(int index) {
if (index < 0 || index > this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+this.size;
}
/**
* 實現fail-fast機制
* 線程不安全 迭代中不允許修改
* @author jiaxiaoxian
* @date 2019年2月12日
*/
private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
}
public Spliterator<E> spliterator() {
checkForComodification();
return new ArrayListSpliterator<E>(ArrayList.this, offset,
offset + this.size, this.modCount);
}
}
11.ArrayListSpliterator內部類--並行迭代,基於索引的二分裂,懶惰初始化的Spliterator
/**
* @since 1.8
* 實例化一個ArrayListSpliterator對象,並返回
*/
@Override
public Spliterator<E> spliterator() {
return new ArrayListSpliterator<>(this, 0, -1, 0);
}
/**
* Index-based split-by-two, lazily initialized Spliterator
* 並行迭代
* 基於索引的二分裂,懶惰初始化的Spliterator
* */
static final class ArrayListSpliterator<E> implements Spliterator<E> {
private final ArrayList<E> list;
private int index; // current index, modified on advance/split
private int fence; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
/** Create new spliterator covering the given range */
ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
int expectedModCount) {
this.list = list; // OK if null unless traversed
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}
private int getFence() { // initialize fence to size on first use
int hi; // (a specialized variant appears in method forEach)
ArrayList<E> lst;
if ((hi = fence) < 0) {
if ((lst = list) == null)
hi = fence = 0;
else {
expectedModCount = lst.modCount;
hi = fence = lst.size;
}
}
return hi;
}
public ArrayListSpliterator<E> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null : // divide range in half unless too small
new ArrayListSpliterator<E>(list, lo, index = mid,
expectedModCount);
}
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
int hi = getFence(), i = index;
if (i < hi) {
index = i + 1;
@SuppressWarnings("unchecked") E e = (E)list.elementData[i];
action.accept(e);
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
public void forEachRemaining(Consumer<? super E> action) {
int i, hi, mc; // hoist accesses and checks from loop
ArrayList<E> lst; Object[] a;
if (action == null)
throw new NullPointerException();
if ((lst = list) != null && (a = lst.elementData) != null) {
if ((hi = fence) < 0) {
mc = lst.modCount;
hi = lst.size;
}
else
mc = expectedModCount;
if ((i = index) >= 0 && (index = hi) <= a.length) {
for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
}
if (lst.modCount == mc)
return;
}
}
throw new ConcurrentModificationException();
}
public long estimateSize() {
return (long) (getFence() - index);
}
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
ArrayList總結
1)arrayList可以存放null,本質是Object[]類型的數組。
2)arrayList區別於數組的地方在於能夠自動擴展大小,其中關鍵的方法就是gorw()方法。
3)arrayList由於本質是數組,所以它在數據的查詢方面會很快,而在插入刪除這些方面,性能下降很多,有移動很多數據才能達到應有的效果,而LinkedList則相反。
4)arrayList實現了RandomAccess,所以在遍歷它的時候推薦使用for循環。
5)初始化數組時推薦給初始長度,反覆擴容會增加時耗,影響性能效率。