程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> JDK1.8源碼閱讀系列之一:ArrayList,jdk1.8arraylist

JDK1.8源碼閱讀系列之一:ArrayList,jdk1.8arraylist

編輯:JAVA綜合教程

JDK1.8源碼閱讀系列之一:ArrayList,jdk1.8arraylist


  本篇隨筆主要描述的是我閱讀 ArrayList 源碼期間的對於 ArrayList 的一些實現上的個人理解,有不對的地方,請指出~

  先來看一下 ArrayList 的繼承圖:

  

  由圖可以看出,ArrayList 的父類有 AbstractList、 AbstractCollection ,所以我從 AbstractCollection 類開始閱讀。

  

  一、AbstractCollection 類相關。

    AbstractCollection 類實現了 Collection 接口,並且由於 AbstractCollection 是一個抽象類,所以它只實現了一些 Collection 接口中的方法,例如 toArray() 方法, contains() 方法, remove() 方法等等。對於Collection 接口中含有的其它方法仍令其保持抽象實現,我認為這樣實現的原因是 :抽象類的作用就是一個概括作用,它需要將其子類中含有的公共方法在抽象類中加以實現,而抽象類中仍然保持抽象的方法一般都是每個子類有自己的實現,在抽象類中是沒有辦法統一起來的。

    在 AbstractCollection 類中,我以為 finishToArray() 方法值得注意一下:

    

  

    finishToArray() 方法是用來給數組 r[] 擴容的,每次當數組 r 的容量不足以容納迭代器遍歷到的元素時,就會對數組 r 進行擴容,並且對擴容後的數組容量進行校驗(hugeCapacity())。

     擴容方法:newCap = cap + (cap >> 1)+ 1; 

 

  二、AbstractList 相關

    AbstractList 也是一個抽象類,其下面具體的子類主要有 LinkedList, ArrayList, Vector幾種。所以 AbstractList 中含有的方法主要是對這幾個具體的子類的抽象。

    我認為 AbstractList 中主要有以下幾點值得注意:

    1、AbstractList 中 iterator() 和 listIterator() 均采用內部類方式實現。

    

 1 public Iterator<E> iterator() {
 2         return new Itr();
 3 }
 4 
 5 public ListIterator<E> listIterator() {
 6         return listIterator(0);
 7 }
 8 
 9 public ListIterator<E> listIterator(final int index) {
10         rangeCheckForAdd(index);
11 
12         return new ListItr(index);
13 }
14 
15 private class Itr implements Iterator<E> {
16     
17             ......
18 
19 }
20 
21 private class ListItr extends Itr implements ListIterator<E> {
22             ......
23 }    

    2、AbstractList 中 removeRange() 方法為我們展示了如何運用迭代器移除 list 指定范圍的元素。

  

1  protected void removeRange(int fromIndex, int toIndex) {
2         ListIterator<E> it = listIterator(fromIndex);
3         for (int i=0, n=toIndex-fromIndex; i<n; i++) {
4             it.next();
5             it.remove();
6         }
7  }

    3、並發修改異常 ConcurrentModificationException

      在 AbstractList 中通過 expectedModCount 和 modCount 兩個量比較來判斷是否產生了並發修改異常,當迭代器在迭代過程中發現 expectedModCount 和 modCount 兩個量不相                 等時就會拋出並發修改異常。modCount 代表改動 list 的次數,當獲得一個 iterator 或者 listIterator 時,就會將 modCount 值賦給 expectedModCount,在迭代器使用的過程中,如果出                 現兩個值不相等的情況 ,就證明有迭代器之外的操作改動了 list,而這很可能會導致迭代器對 list 的操作出現錯誤,所以在接下來使用迭代器的時候就會拋出異常,這就是並發修改異                 常的作用。

 

    4、AbstractList 中的 subList() 方法。

      先來看下 subList() 方法的實現:

      

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
       ......
        public List<E> subList(int fromIndex, int toIndex) {
            return (this instanceof RandomAccess ?
                new RandomAccessSubList<>(this, fromIndex, toIndex) :
                new SubList<>(this, fromIndex, toIndex));
        }
        ......
}
class SubList<E> extends AbstractList<E> {
    SubList(AbstractList<E> list, int fromIndex, int toIndex) {
        l = list;
        offset = fromIndex;
        size = toIndex - fromIndex;
        this.modCount = l.modCount;
    }
    public E set(int index, E element) {
        return l.set(index+offset, element);
    }
        ......
}
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
    RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
        super(list, fromIndex, toIndex);
    }
        ......   
}

 

 

      可見有 SubList 與 RandomAccessSubList 兩種,區別在於是否實現 RandomAccess 接口 ,也就是是否可以隨機讀取,例如 ArrayList 可以隨機讀取,而 LinkedList 則只能順序讀                 取。在SubList類的構造方法中,獲取了一個 AbstractList 類的引用,作用是利用這個引用實現 SubList 中的相關方法。

      也就是說,subList 幾乎所有方法都是基於 AbstractList 類實現的,對於 subList  返回的 list 所做的所有改動都會反應到原來的 list 當中去。

 

  三、ArrayList 相關

     

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved