java容器類分析:Collection,List,ArrayList,

來源:互聯網
上載者:User

java容器類分析:Collection,List,ArrayList,
1、 Iterable 與 Iterator

Iterable 是個介面,實現此介面使集合對象可以通過迭代器遍曆自身元素.

public interface Iterable<T>

修飾符和傳回值 方法名 描述
Iterator<T> iterator() 返回一個內部元素為T類型的迭代器
default void forEach(Consumer<? super T> action) 對內部元素進行遍曆,並對元素進行指定的操作
default Spliterator<T> spliterator() 建立並返回一個可分割迭代器

第一個介面iterator()是jdk1.5引入的,需要子類實現一個內部迭代器Iterator遍曆元素。

後兩個介面是JDK1.8後新添加的,forEach(Consumer action)是為了方便遍曆操作集合內的元素,spliterator()則提供了一個可以並行遍曆元素的迭代器,以適應現在cpu多核時代並行遍曆的需求.

其中我們可以看下default修飾符,這也是Java 8後新出現的,我們知道,如果我們給一個介面新添加一個方法,那麼所有他的具體子類都必須實現此方法,為了能給介面拓展新功能,而又不必每個子類都要實現此方法,Java 8新加了default關鍵字,被其修飾的方法可以不必由子類實現,並且由dafault修飾的方法在介面中有方法體,這打破了Java之前對介面方法的規範.

Iterator 為迭代器類,用於遍曆容器。

public interface Iterator<E>

修飾符和傳回值 方法名 描述
boolean hasNext() 判斷迭代器所指元素是否為最後一個
E next() 下一個元素
default Void remove() 移除迭代器只想的當前元素
default Void forEachRemaining(Consumer<? super E> action) 遍曆迭代器指向元素後面的所有元素

AbstartList中實現了Iterator類作為List內部的迭代器,用於訪問內部元素,其代碼如下:

  1 private class Itr implements Iterator<E> {  2         /**  3          * Index of element to be returned by subsequent call to next.  4          */  5         int cursor = 0;  6   7         /**  8          * Index of element returned by most recent call to next or  9          * previous.  Reset to -1 if this element is deleted by a call 10          * to remove. 11          */ 12         int lastRet = -1; 13  14         /** 15          * The modCount value that the iterator believes that the backing 16          * List should have.  If this expectation is violated, the iterator 17          * has detected concurrent modification. 18          */ 19         int expectedModCount = modCount; 20  21         public boolean hasNext() { 22             return cursor != size(); 23         } 24  25         public E next() { 26             checkForComodification(); 27             try { 28                 int i = cursor; 29                 E next = get(i); 30                 lastRet = i; 31                 cursor = i + 1; 32                 return next; 33             } catch (IndexOutOfBoundsException e) { 34                 checkForComodification(); 35                 throw new NoSuchElementException(); 36             } 37         } 38  39         public void remove() { 40             if (lastRet < 0) 41                 throw new IllegalStateException(); 42             checkForComodification(); 43  44             try { 45                 AbstractList.this.remove(lastRet); 46                 if (lastRet < cursor) 47                     cursor--; 48                 lastRet = -1; 49                 expectedModCount = modCount; 50             } catch (IndexOutOfBoundsException e) { 51                 throw new ConcurrentModificationException(); 52             } 53         } 54  55         final void checkForComodification() { 56             if (modCount != expectedModCount) 57                 throw new ConcurrentModificationException(); 58         } 59     } 60 
View Code2、Collection

Collection 是容器類的介面,裡面可以存放很多Elements,很多容器都實現了該介面。

public interface Collection<E> extends Iterable<E>

修飾符和傳回值 方法名 描述
int size() 判斷容器的大小
boolean isEmpty() 判空
boolean contains(Object o) 是否包含某元素
Object[] toArray() 轉化為數組
<T> T[] toArray(T[] a) 將容器中所有元素拷貝到a中,如果a不夠大,則拷貝到返回的數組中。(見AbstactCollection中實現)
boolean add(E e) 添加元素
boolean remove(Object o) 移除容器中第一個出現Object對象,如果Object為null,則移除第一個出現的null。如果沒有Object對象返回false
boolean containsAll(Collection<?> c) 包含c中所有元素
boolean addAll(Collection<? extends E> c); 將c中所有元素添加到容器中
boolean removeAll(Collection<?> c) 如果容器中包含c中的元素,刪除。(調用remove(Object))
default boolean removeIf(Predicate<? super E> filter) 移除所有合格元素(JDK1.8中引入)
boolean retainAll(Collection<?> c) 保留在c中出現的元素,其它全部移除
boolean clear()  
boolean equals(Object o) 與o中所有元素都相等則相等
int  hashCode() c1.equals(c2) 那麼他們的hashCode()一定相等,反之不成立 
default Spliterator<E> spliterator() 在所有元素之上建立一個Spliterator
default Stream<E> stream()  
default Stream<E> parallelStream()  

上述很多函數的實現可以參考 AbstactList中的實現。

3. List

List是一個介面,繼承了Collection中的所有介面,並且添加了自身相關介面和具體實現。

由可以看出,Collection分成了三個分支,List就是其中一個,下面我們具體分析一下增加的介面。

public interface List<E> extends Collection<E>

修飾符和傳回值 方法名 描述
  Collection中的所有介面  
default void  replaceAll(UnaryOperator<E> operator) 將運算操作後的結果替換List中原有元素
default void sort(Comparator<? super E> c) 將List中所有元素排序
get(int index);  
set(int index, E element)  
remove(int index)  
int indexOf(Object o) o在List中第一次出現的位置
int lastIndexOf(Object o) o在List中最後一次出現的位置
ListIterator<E> listIterator() 擷取List的迭代器
ListIterator<E> listIterator(int index) 擷取從某個位置開始的迭代器,index為迭代器起始位置
List<E> subList(int fromIndex, int toIndex) 子List

上表可以看出,增加了 和index相關的介面,根據index對List進行的get、set、remove等操作。另一類添加的介面是ListIteator相關的,擷取List的迭代器。

3.1 ListIterator

public interface ListIterator<E> extends Iterator<E>

ListIterator 不光包含Iterator中的三個介面還增加了作為一個List迭代器應該有的介面,如 next(),previous()等

修飾符和傳回值 方法名 描述
  Iterator中的所有介面  
boolean  hasNext()  
E next()  
boolean  hasPrevious()  
E previous()  
int nextIndex()  
int previousIndex()  
void  remove() 刪除next()返回元素
void  set(E e) 替換next()返回的元素
void  add(E e) 在nextIndex()後插入元素

首先需要明確ListIterator迭代器的作用:

注意,迭代器 沒有當前所在元素一說,它只有一個遊標( cursor )的概念,這個遊標總是在元素之間,比如這樣:

迭代器的初始位置:

調用next()後迭代器的位置

調用 previous() 遊標就會回到之前位置。當向後遍曆完元素,遊標就會在元素 N 的後面

也就是說長度為 N 的集合會有 N+1 個遊標的位置。

3.2 AbstractCollection / AbstractList

        在上面的繼承關係圖中並沒有顯示出AbstractCollect和AbstractList的存在,但是在閱讀源碼的時候經常遇到這兩個類,下面講一下這兩個類的作用。

      首先需要明確的一點是AbstractCollect和AbstractList都是抽象類別而不是介面,它們分別實現了Collection和List介面中的部分函數。這樣繼承者直接繼承AbstractXXXX 而不需要自己重複實現裡面的所有介面。這兩個抽象類別抽離了公用部分,進行了實現,減少後續類的工作量。

       ArrayList 和LinkedList都直接或者間接繼承了AbstartList類。為這兩個類的繼承關係:

        具體這兩個類裡面實現了哪些介面,請自己閱讀源碼不再講解。

3.3 ArrayList

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable我們看到ArrayList的定義的時候很可能會出現一個疑問,為什麼它已經繼承了AbstractList了還需要去實現List<E>介面? 答案是,後面的List<E>可以去掉,這裡只是讓閱讀者明白ArrayList是個List。 終於好不容易到了開發人員常用的類了,有點竊喜:transient Object[] elementData;這個很重要的成員變數elementData數組用來存放ArrayList中的元素,當第一個元素添加進來後,它的預設長度變為10。(java中“transient”關鍵字修飾的成員變數在類序列化的過程中不會被持久化到檔案中,保證該成員變數儲存資訊的安全。)
ArrayList的建構函式中可以直接指定elementData數組的長度,那麼問題來了,當數組已經完全被佔用再向ArrayList中添加元素時,如何再分配更大長度的數組?如何把舊資料拷貝到新數組中?答案見下面這段源碼

  1 private void grow(int minCapacity) {  //最少需要的容量   2         // overflow-conscious code  3         int oldCapacity = elementData.length;  4         int newCapacity = oldCapacity + (oldCapacity >> 1);   // 分配最小容量的 1.5倍  5         if (newCapacity - minCapacity < 0)         6             newCapacity = minCapacity;  7         if (newCapacity - MAX_ARRAY_SIZE > 0)  8             newCapacity = hugeCapacity(minCapacity);   // 最大容量比較(Inter.MAX_VALUE)  9         // minCapacity is usually close to size, so this is a win: 10         elementData = Arrays.copyOf(elementData, newCapacity);  // 將舊資料拷貝到新數組中 11     }

其它介面不再細說。
參考:https://www.cnblogs.com/bushi/p/6647006.html

https://www.jianshu.com/p/047e33fdefd2

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.