1. 程式人生 > >Java基礎系列(四十二):集合之AbstractList

Java基礎系列(四十二):集合之AbstractList

前言

AbstractList是實現List介面的一個抽象類,它的地位之與List類似於AbstractCollection之與Collection,同事,AbstractList繼承了AbstractCollection,並針對List介面給出了一些預設的實現。而且它是針對隨機訪問儲存資料的方式的,如果需要使用順序訪問儲存資料方式,還有一個AbstractSequentialListAbstractList的子類,順序訪問時應該優先使用它。

框架圖

在這裡插入圖片描述

原始碼

接下來,我們來看一下AbstractList的原始碼,看看他針對於List介面相較於AbstractCollection

給出了哪些不同的實現方法。



package java.util;


public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    
    //只提供了一個protected修飾的無參構造器,供子類使用。
    protected AbstractList() {
    }

    //新增一個元素,實際上並沒有實現。
    public boolean add(E e) {
        //實際上,size()在這個方法中並沒有實現,交由子類去實現。
add(size(), e); return true; } //抽象方法,需要子類去實現,根據索引值獲取集合中的某個元素(隨機訪問) abstract public E get(int index); //由於該集合是不可變的,所以一切可能會改變集合元素的操作都會丟擲一個UnsupportedOperationException() public E set(int index, E element) { throw new UnsupportedOperationException(); } public
void add(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); } // Search Operations //獲取某個元素在集合中的索引 public int indexOf(Object o) { //這裡是由AbstractList內部已經提供了Iterator, ListIterator迭代器的實現類,分別為Itr,ListItr。這裡是呼叫了一個例項化ListItr的方法 ListIterator<E> it = listIterator(); if (o==null) { while (it.hasNext()) if (it.next()==null) return it.previousIndex(); } else { while (it.hasNext()) if (o.equals(it.next())) return it.previousIndex(); } //如果集合中不存在該元素,返回-1 return -1; } //獲取某個元素在集合中最後一次出現的索引 public int lastIndexOf(Object o) { ListIterator<E> it = listIterator(size()); if (o==null) { while (it.hasPrevious()) if (it.previous()==null) return it.nextIndex(); } else { while (it.hasPrevious()) if (o.equals(it.previous())) return it.nextIndex(); } return -1; } // Bulk Operations //清除集合中的元素 public void clear() { removeRange(0, size()); } //從某個索引開始,將c中的元素全部插入到集合中 public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); boolean modified = false; for (E e : c) { add(index++, e); modified = true; } return modified; } // Iterators //獲取Iterator介面Itr實現類迭代器 public Iterator<E> iterator() { return new Itr(); } //獲取從0開始(初始位置)的ListIterator的實現類ListItr public ListIterator<E> listIterator() { return listIterator(0); } //獲取從索引等於index的位置的迭代器 public ListIterator<E> listIterator(final int index) { rangeCheckForAdd(index); return new ListItr(index); } /** * 內部實現了Iterator介面的實現類Itr */ private class Itr implements Iterator<E> { //游標位置 int cursor = 0; //上一次迭代到的元素的游標位置,如果是末尾會置為-1 int lastRet = -1; //併發標誌,如果兩個值不一致,說明發生了併發操作,就會報錯 int expectedModCount = modCount; //判斷是否存在下一條資料,即迭代器的位置是否走到尾 public boolean hasNext() { //如果游標位置不等於集合個數,說明迭代器沒有走到末尾,返回true return cursor != size(); } //獲取下一個元素 public E next() { //判斷是否有併發操作 checkForComodification(); try { int i = cursor; //通過索引位置來獲取元素 E next = get(i); lastRet = i; //每次將+1,將迭代器位置向後移動一位 cursor = i + 1; return next; } catch (IndexOutOfBoundsException e) { //時刻檢查是否有併發操作 checkForComodification(); throw new NoSuchElementException(); } } //刪除上一次迭代器越過的元素 public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { //呼叫需要子類去實現的remove方法 AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--; //每次刪除後,將lastRet置為-1,防止連續的刪除 lastRet = -1; //將修改次數賦給迭代器對物件的結構修改次數這個會在下面進行詳解 expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { //如果出現索引越界,說明發生了併發的操作導致,所以丟擲一個併發操作異常。 throw new ConcurrentModificationException(); } } //判斷是否發生了併發操作 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } //繼承自Itr的ListIterator的實現類ListItr private class ListItr extends Itr implements ListIterator<E> { //指定游標位置等於索引的迭代器構造 ListItr(int index) { cursor = index; } //如果不是第一位,返回true public boolean hasPrevious() { return cursor != 0; } //獲取上一位的元素,這裡在後面會有畫圖幫助理解 public E previous() { checkForComodification(); try { //這裡和父類的寫法略有不同,先將游標的位置進行減一 int i = cursor - 1; E previous = get(i); //因為需要返回的是前一位的元素,所以這裡的游標值和上一次迭代到的游標的位置實際上是一樣的 lastRet = cursor = i; return previous; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } //下一位的索引值等於游標值 public int nextIndex() { return cursor; } //上一位的索引值等於游標值減一 public int previousIndex() { return cursor-1; } //設定元素 public void set(E e) { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { //預設設定的位置是上一次迭代器越過的元素 AbstractList.this.set(lastRet, e); expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } //新增元素 public void add(E e) { checkForComodification(); try { //設定新增的位置為當前游標所在的位置 int i = cursor; AbstractList.this.add(i, e); //這裡講lastRet設定為-1,即新增的元素不允許立即刪除 lastRet = -1; //新增後,將游標移到 cursor = i + 1; //迭代器併發標誌和集合併發標誌統一 expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { //如果出現了索引越界,說明發生了併發操作 throw new ConcurrentModificationException(); } } } //切取子List public List<E> subList(int fromIndex, int toIndex) { //是否支援隨機訪問 return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : new SubList<>(this, fromIndex, toIndex)); } // Comparison and hashing //通過迭代器來遍歷進行判斷每項是否相等來重寫equals方法 public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof List)) return false; ListIterator<E> e1 = listIterator(); ListIterator<?> e2 = ((List<?>) o).listIterator(); while (e1.hasNext() && e2.hasNext()) { E o1 = e1.next(); Object o2 = e2.next(); if (!(o1==null ? o2==null : o1.equals(o2))) return false; } return !(e1.hasNext() || e2.hasNext()); } //重寫hashCode public int hashCode() { int hashCode = 1; for (E e : this) hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); return hashCode; } //使用迭代器成段刪除集合中的元素 protected void removeRange(int fromIndex, int toIndex) { ListIterator<E> it = listIterator(fromIndex); for (int i=0, n=toIndex-fromIndex; i<n; i++) { it.next(); it.remove(); } } //? protected transient int modCount = 0; //判斷索引是否越界 private void rangeCheckForAdd(int index) { if (index < 0 || index > size()) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size(); } } //繼承自AbstractList的內部類SubList,代表了它父類的一部分 class SubList<E> extends AbstractList<E> { private final AbstractList<E> l; private final int offset; private int size; //根據父類來構造一個SubList SubList(AbstractList<E> list, int fromIndex, int toIndex) { if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); if (toIndex > list.size()) throw new IndexOutOfBoundsException("toIndex = " + toIndex); if (fromIndex > toIndex) throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); l = list; offset = fromIndex; size = toIndex - fromIndex; //修改次數(併發標誌)和父類保持一致 this.modCount = l.modCount; } //實際上還是呼叫的父類的set方法和get方法 public E set(int index, E element) { rangeCheck(index); checkForComodification(); return l.set(index+offset, element); } public E get(int index) { rangeCheck(index); checkForComodification(); return l.get(index+offset); } //size = toIndex - fromIndex; public int size() { checkForComodification(); return size; } public void add(int index, E element) { rangeCheckForAdd(index); checkForComodification(); //實際上還是在父類上進行新增 l.add(index+offset, element); this.modCount = l.modCount; //然後把size + 1 size++; } public E remove(int index) { rangeCheck(index); checkForComodification(); //實際上還是在父類上進行刪除 E result = l.remove(index+offset); this.modCount = l.modCount; size--; return result; } protected void removeRange(int fromIndex, int toIndex) { checkForComodification(); //呼叫父類的removeRange方法 l.removeRange(fromIndex+offset, toIndex+offset); this.modCount = l.modCount; size -= (toIndex-fromIndex); } public boolean addAll(Collection<? extends E> c) { return addAll(size, c); } public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); int cSize = c.size(); if (cSize==0) return false; checkForComodification(); //在當前的子集合開始的位置進行插入 l.addAll(offset+index, c); this.modCount = l.modCount; size += cSize; return true; } public Iterator<E> iterator() { return listIterator(); } public ListIterator