java集合系列 02 Collection
概要
首先,對Collection進行說明。下面是Collection的繼承關係的主要類圖,(這裏只列舉了抽象類和接口,來說明Collection的整體結構)
Collection是一個接口,它主要的倆個分支是:List 和Set。
List和Set都是接口,他們繼承於Collection。
List是有序隊列,這裏所說的有序隊列是指,按照什麼順序添加,可以以相同的順序取出來,List中可以有相同的元素。
Set可以和數學概念中的集合類比,Set中不允許有重複的元素。
由上面的類圖可以看出,首先抽象出了一個AbstractCollection抽象類,實現了Collection接口中的大部分方法,方便後面代碼的編寫。接着AbstractList 和 AbstractSet繼承了AbstractCollection。其中AbstraList實現了List中特有的一寫方法,AbstractSet實現了對於Set來說通用的一些方法。這樣做可以方便子類的編寫。這很好的體現了面向對象的思想。
另外要說明的一點是,Collection繼承了Iterator接口,所以每一個實現了Collection接口的類中,都可以使用迭代器遍歷。List系列的集合實現了一個特有的ListIterator接口,在這個接口中增加了一些添加,刪除等方法。
通過上面的介紹可以發現,Collection體系中的集合並不是特別的複雜,所以只要細心的理一下,還是很容易理解和使用的。java 8新增加了default方法,還有流(Stream),因爲我們關注的是集合的使用,因此在這裏就省略這部分內容。後面我會專門寫一系列的博客來講解java8中的流。
主要內容
Collection 簡介
List 簡介
Set 簡介
AbstractCollection 源碼分析
AbstractList 源碼分析
AbstractSet 源碼分析
ListIterator
注:Iterator 請看我的另一篇博客Iterator 和 iterable 區別
1. Collection 簡介
Collection 定義如下
public interface Collection<E> extends Iterable<E>{}
本身是一個接口,高度抽象出來集合,它包含了集合的基本操作:添加、刪除、清空、遍歷、、是否爲空、獲取大小、是否保護某元素等等。
在Java API規定,所有實現Collection接口的子類(直接子類和間接子類)都必須實現倆種構造參數:不帶參數的構造參數(爲了創建出一個空的集合類)和帶參數的構造參數(用參數創建出一個新的集合類,也就是可以轉換集合類)。
//Collection 接口 public abstract boolean add(E e) //添加元素 public abstract boolean add(Collection<? extend E> c) //添加集合 public abstract void clear() //清空集合 public abstract boolean contains(Object o) //判斷集合是否包含此元素 public abstract boolean containsAll(Collection<?> c) //判斷集合中是否包含參數集合中所有的元素 public abstract boolean equals(Object object) //比較倆個是否相同 public abstract int hashCode() //返回hash值 public abstract boolean isEmpty() //是否爲空 public abstract Iterator<E> iterator() //返回迭代器 public abstract boolean remove(Object object) //刪除某個元素 public abstract boolean removeAll(Collection<?> collection) //刪除參數中的元素 public abstract boolean retainAll(Collection?> collection) //保留參數集合中元素 public abstract int size() //返回集合的大小 public abstract <T> T[] toArray(T[] array) //返回T類型的數組 public abstract Object[] toArray() //返回包含集合所有元素的集,是Object類型
2. List 簡介
List 定義如下:
public interface List<E> extends Collection<E> {}
List 是一個繼承了Collection的接口,是集合的一種,是一個有序集合。List中的每一個集合都有一個索引,第一個元素的索引是0,往後的元素一次加1,List中允許有重複的元素
關於API方面。既然List是繼承於Collection接口,它自然就包含了Collection中的全部函數接口;由於List是有序隊列,它也額外的有自己的API接口。主要有“添加、刪除、獲取、修改指定位置的元素”、“獲取List中的子隊列”等。
// 相比與Collection,List新增的API: abstract void add(int location, E object) //在指定的位置增加元素 //在指定的位置開始增加元素 abstract boolean addAll(int location, Collection<? extends E> c) abstract E get(int location) //得到指定位置的元素 abstract int indexOf(Object object) //返回第一個出現出現元素的索引 abstract int lastIndexOf(Object object) //返回最後一個出現出現元素的索引 abstract ListIterator<E> listIterator(int location) //從location位置開始返回 abstract ListIterator<E> listIterator()//返回listIterator對象 abstract E remove(int location) abstract E set(int location, E object) //替換某個位置的元素 abstract List<E> subList(int start, int end) //返回當前List的子集
3. Set 簡介
Set的定義如下:
public interface Set<E> extends Collection<E> {}
Set是一個繼承與Collection的接口,也是集合中的一種。Set是不允許有重複元素的集合
在API上,和Collection完全一樣
4. AbstractCollection
AbstractCollection 定義如下:
public abstract class AbstractCollection<E> implements Collection<E> {}
AbstractCollection 是一個抽象類,他實現了Collection中除Iterator()和size()之外的函數
AbstractCollection的主要作用:它實現了Collection接口中的大部分函數。從而方便其它類實現Collection,比如ArrayList、LinkedList等,它們這些類想要實現Collection接口,通過繼承AbstractCollection就已經實現了大部分的接口了。
另外在集合中,很多的操作都是依賴於迭代器。而不同類型的集合迭代器的實現方式可能不同,因此實現迭代器一般都會放在子類中實現。
//對AbstractCollection的源碼分析 package java.util; public abstract class AbstractCollection<E> implements Collection<E> { protected AbstractCollection() { } // 查詢操作 //有collection的子類有不同的種類 //因此不同種類的迭代器可能不相同,這裏就沒有實現 public abstract Iterator<E> iterator(); //返回當前集合的大小 public abstract int size(); //判斷當前集合是否爲空, //只要size等於0說明沒有元素 public boolean isEmpty() { return size() == 0; } //由於每個集合都有迭代器, //因此可以通過迭代器進行遍歷, //然後判斷指定元素是否存在 public boolean contains(Object o) { Iterator<E> it = iterator(); if (o == null) { while (it.hasNext()) if (it.next() == null) return true; } else { while (it.hasNext()) if (o.equals(it.next())) return true; } return false; } //返回object類型的數組, public Object[] toArray() { // 先得到一個預期的集合大小,爲了防止在遍歷是有其他線程修改了集合 Object[] r = new Object[size()]; Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++) { if (!it.hasNext()) // 少於預期的集合大小,返回一個和新的集合大小相同數組 return Arrays.copyOf(r, i); r[i] = it.next(); } //如果預期的大小小於集合的size,則利用finishToArray返回這個集合最終轉換的數組 return it.hasNext() ? finishToArray(r, it) : r; } //返回指定指定類型的數組,不是object類型的 @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { // 先得到一個預期的集合大小,爲了防止在遍歷是有其他線程修改了集合 int size = size(); //通過反射創建指定類型的數組 T[] r = a.length >= size ? a : (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++) { if (!it.hasNext()) { // 少於預期的大小 if (a == r) { r[i] = null; // null-terminate } else if (a.length < i) { return Arrays.copyOf(r, i); } else { System.arraycopy(r, 0, a, 0, i); if (a.length > i) { a[i] = null; } } return a; } r[i] = (T) it.next(); } // 超過預期的集合大小 return it.hasNext() ? finishToArray(r, it) : r; } //數組的最大長度,有虛擬機內部會在array頭部存儲一些信息, //因此最大長度沒有達到Integer的最大值 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //當在進行toArray操作時,集合大小發生改變, //則會使用下面的操作,重新分配數組的大小,並進行拷貝 @SuppressWarnings("unchecked") private static <T> T[] finishToArray(T[] r, Iterator<?> it) { int i = r.length; while (it.hasNext()) { int cap = r.length; if (i == cap) { int newCap = cap + (cap >> 1) + 1; // overflow-conscious code if (newCap - MAX_ARRAY_SIZE > 0) newCap = hugeCapacity(cap + 1); r = Arrays.copyOf(r, newCap); } r[i++] = (T) it.next(); } // 如果數組的實際長度和當前數組的長度不相等,則縮短當前數組的長度 return (i == r.length) ? r : Arrays.copyOf(r, i); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError("Required array size too large"); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } // 修改集合操作 // 添加操作 public boolean add(E e) { throw new UnsupportedOperationException(); } //通過迭代器移除和當前對象所匹配的元素 //只會移除1個 public boolean remove(Object o) { Iterator<E> it = iterator(); if (o == null) { while (it.hasNext()) { if (it.next() == null) { it.remove(); return true; } } } else { while (it.hasNext()) { if (o.equals(it.next())) { it.remove(); return true; } } } return false; } // 批量操作 // 判斷給定的集合是否在當前collection中都存在 public boolean containsAll(Collection<?> c) { for (Object e : c) if (!contains(e)) return false; return true; } //添加集合 public boolean addAll(Collection<? extends E> c) { boolean modified = false; for (E e : c) if (add(e)) modified = true; return modified; } //刪除當前集合中和參數給定集合匹配的元素 public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); boolean modified = false; Iterator<?> it = iterator(); while (it.hasNext()) { if (c.contains(it.next())) { it.remove(); modified = true; } } return modified; } //保留當前集合中和參數給定集合匹配的元素 public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); boolean modified = false; Iterator<E> it = iterator(); while (it.hasNext()) { if (!c.contains(it.next())) { it.remove(); modified = true; } } return modified; } //清空元素,利用迭代器裏面的remove //如果沒有實現這個方法 //則拋出不支持該操作異常 public void clear() { Iterator<E> it = iterator(); while (it.hasNext()) { it.next(); it.remove(); } } // 返回當前collection元素組成的string public String toString() { Iterator<E> it = iterator(); if (!it.hasNext()) return "[]"; StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { E e = it.next(); sb.append(e == this ? "(this Collection)" : e); if (!it.hasNext()) return sb.append(']').toString(); sb.append(',').append(' '); } } }
5. AbstractList
AbstractList的定義如下:
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {}
AbstractList是一個繼承於AbstractCollection,並且實現List接口的抽象類。
AbstractList的主要作用:它實現了List接口中的大部分函數。從而方便其它集合類繼承List。
另外,和AbstractCollection相比,AbstractList抽象類中,實現了iterator()接口。
有以下的方法沒有實現
1. public abstract E get(int var1) 2. public E set(int var1, E var2) 3. public void add(int var1, E var2) 4. public E remove(int var1)
package java.util; public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { //當前list的修改操作次數,用於fail-fast決策 protected transient int modCount = 0; protected AbstractList() { } //在末尾增加元素 public boolean add(E var1) { this.add(this.size(), var1); return true; } //得到指定位置的元素 //需要子類實現 public abstract E get(int var1); //替換指定位置的元素 //如果未實現則拋出不支持操作異常 public E set(int var1, E var2) { throw new UnsupportedOperationException(); } //在指定位置增加元素 //如果未實現則拋出不支持操作 public void add(int var1, E var2) { throw new UnsupportedOperationException(); } //移除指定位置元素 //如果未實現,則拋出不支持操作 public E remove(int var1) { throw new UnsupportedOperationException(); } //搜索操作 //利用listIterator來搜索指定元素 //包含null類型的元素 //搜索不到返回 -1 //如果有,返回第一個匹配元素的索引 public int indexOf(Object var1) { ListIterator var2 = this.listIterator(); if (var1 == null) { while (var2.hasNext()) { if (var2.next() == null) { return var2.previousIndex(); } } } else { while (var2.hasNext()) { if (var1.equals(var2.next())) { return var2.previousIndex(); } } } return -1; } //利用listIterator來搜索指定元素 //包含null類型的元素 //搜索不到返回 -1 //如果有,返回最後一個匹配元素的索引 public int lastIndexOf(Object var1) { ListIterator var2 = this.listIterator(this.size()); if (var1 == null) { while (var2.hasPrevious()) { if (var2.previous() == null) { return var2.nextIndex(); } } } else { while (var2.hasPrevious()) { if (var1.equals(var2.previous())) { return var2.nextIndex(); } } } return -1; } //清空元素 public void clear() { this.removeRange(0, this.size()); } //在指定位置之後添加集合 public boolean addAll(int var1, Collection<? extends E> var2) { this.rangeCheckForAdd(var1); boolean var3 = false; for (Iterator var4 = var2.iterator(); var4.hasNext(); var3 = true) { Object var5 = var4.next(); this.add(var1++, var5); } return var3; } //得到迭代器 public Iterator<E> iterator() { return new AbstractList.Itr(); } //得到list特有的ListIterator迭代器 public ListIterator<E> listIterator() { return this.listIterator(0); } //從指定元素位置開始 //創建一個新的迭代器 public ListIterator<E> listIterator(int var1) { this.rangeCheckForAdd(var1); return new AbstractList.ListItr(var1); } public List<E> subList(int var1, int var2) { return (List) (this instanceof RandomAccess ? new RandomAccessSubList(this, var1, var2) : new SubList(this, var1, var2)); } public boolean equals(Object var1) { if (var1 == this) { return true; } else if (!(var1 instanceof List)) { return false; } else { ListIterator var2 = this.listIterator(); ListIterator var3 = ((List) var1).listIterator(); while (true) { if (var2.hasNext() && var3.hasNext()) { Object var4 = var2.next(); Object var5 = var3.next(); if (var4 == null) { if (var5 == null) { continue; } } else if (var4.equals(var5)) { continue; } return false; } return !var2.hasNext() && !var3.hasNext(); } } } public int hashCode() { int var1 = 1; Object var3; for (Iterator var2 = this.iterator(); var2.hasNext(); var1 = 31 * var1 + (var3 == null ? 0 : var3.hashCode())) { var3 = var2.next(); } return var1; } protected void removeRange(int var1, int var2) { ListIterator var3 = this.listIterator(var1); int var4 = 0; for (int var5 = var2 - var1; var4 < var5; ++var4) { var3.next(); var3.remove(); } } //檢測添加的位置範圍是否合適 private void rangeCheckForAdd(int var1) { if (var1 < 0 || var1 > this.size()) { throw new IndexOutOfBoundsException(this.outOfBoundsMsg(var1)); } } //設置超出集合界限的模板消息 private String outOfBoundsMsg(int var1) { return "Index: " + var1 + ", Size: " + this.size(); } //藉助於Iterator實現雙向鏈表, private class ListItr extends AbstractList<E>.Itr implements ListIterator<E> { ListItr(int var2) { super(null); this.cursor = var2; } public boolean hasPrevious() { return this.cursor != 0; } public E previous() { this.checkForComodification(); try { int var1 = this.cursor - 1; Object var2 = AbstractList.this.get(var1); this.lastRet = this.cursor = var1; return var2; } catch (IndexOutOfBoundsException var3) { this.checkForComodification(); throw new NoSuchElementException(); } } public int nextIndex() { return this.cursor; } public int previousIndex() { return this.cursor - 1; } public void set(E var1) { if (this.lastRet < 0) { throw new IllegalStateException(); } else { this.checkForComodification(); try { AbstractList.this.set(this.lastRet, var1); this.expectedModCount = AbstractList.this.modCount; } catch (IndexOutOfBoundsException var3) { throw new ConcurrentModificationException(); } } } public void add(E var1) { this.checkForComodification(); try { int var2 = this.cursor; AbstractList.this.add(var2, var1); this.lastRet = -1; this.cursor = var2 + 1; this.expectedModCount = AbstractList.this.modCount; } catch (IndexOutOfBoundsException var3) { throw new ConcurrentModificationException(); } } } // 實現list通用的迭代器, // 主要藉助的是外部類的兩個方法,remove(int) 和 get(int) private class Itr implements Iterator<E> { int cursor; //當前迭代器指向的位置 int lastRet; //指向next操作的前一個元素 int expectedModCount; //外部集合類修改集合的次數,用於fail-fast private Itr() { this.cursor = 0; //開始的位置 this.lastRet = -1; //沒有開始進行迭代操作 //外部集合類修改集合的次數,用於fail-fast this.expectedModCount = AbstractList.this.modCount; } //利用當前指向的遊標和外部類list的大小來判斷是否還有下一個元素 public boolean hasNext() { return this.cursor != AbstractList.this.size(); } //返回元素 public E next() { //首先利用fail-fast來檢測list是否改變, this.checkForComodification(); try { int var1 = this.cursor; //藉助外部集合類得到指定位置的元素 Object var2 = AbstractList.this.get(var1); this.lastRet = var1; this.cursor = var1 + 1; return var2; } catch (IndexOutOfBoundsException var3) { //捕獲超出邊界異常 //判斷是否是當前list被併發修改,如果是,則拋出此異常 this.checkForComodification(); throw new NoSuchElementException(); //正常拋出異常 } } //實現Iterator 接口 的remove方法 public void remove() { if (this.lastRet < 0) { throw new IllegalStateException(); } else { this.checkForComodification(); try { //藉助外部類的remove方法進行刪除 AbstractList.this.remove(this.lastRet); if (this.lastRet < this.cursor) { //當期那遊標減1 --this.cursor; } this.lastRet = -1; //重新設置list的大小 this.expectedModCount = AbstractList.this.modCount; } catch (IndexOutOfBoundsException var2) { throw new ConcurrentModificationException(); } } } // 判斷list是否已經修改, // 如果修改則拋出併發修改錯誤 final void checkForComodification() { if (AbstractList.this.modCount != this.expectedModCount) { throw new ConcurrentModificationException(); } } } }
6 AbstractSet
AbstractSet的定義如下:
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {}
AbstractSet是一個繼承於AbstractCollection,並且實現Set接口的抽象類。由於Set接口和Collection接口中的API完全一樣,Set也就沒有自己單獨的API。
和AbstractCollection一樣,它實現了List中除iterator()和size()之外的函數。
AbstractSet的主要作用:它實現了Set接口中的大部分函數。從而方便其它類實現Set接口。
7 ListIterator
ListIterator的定義如下:
public interface ListIterator<E> extends Iterator<E> {}
ListIterator是一個繼承於Iterator的接口,它是隊列迭代器。專門用於便利List,能提供向前/向後遍歷。相比於Iterator,它新增了添加、是否存在上一個元素、獲取上一個元素等等API接口。
// ListIterator的API // 繼承於Iterator的接口 abstract boolean hasNext() abstract E next() abstract void remove() // 新增API接口 abstract void add(E object) abstract boolean hasPrevious() abstract int nextIndex() abstract E previous() abstract int previousIndex() abstract void set(E object)