List
是Collection
三大直接子接口之一,其中的數據能夠經過位置檢索,用戶能夠在指定位置插入數據。List
的數據能夠爲空,能夠重複。如下是其文檔註釋,只看前兩段:java
An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.多線程
Unlike sets, lists typically allow duplicate elements. More formally, lists typically allow pairs of elements <tt>e1</tt> and e2 such that e1.equals(e2), and they typically allow multiple null elements if they allow null elements at all. It is not inconceivable that someone might wish to implement a list that prohibits duplicates, by throwing runtime exceptions when the user attempts to insert them, but we expect this usage to be rare.app
咱們關注其不一樣於Collection的方法,主要有如下這些:ide
//在指定位置,將指定的集合插入到當前的集合中 boolean addAll(int index, Collection<? extends E> c); //這是一個默認實現的方法,會經過Iterator的方式對每一個元素進行指定的操做 default void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); final ListIterator<E> li = this.listIterator(); while (li.hasNext()) { li.set(operator.apply(li.next())); } } //排序,依據指定的規則對當前集合進行排序,能夠看到,排序是經過Arrays這個工具類完成的。 default void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } } //獲取指定位置的元素 E get(int index); //修改指定位置元素的值 E set(int index, E element); //將指定元素添加到指定的位置 void add(int index, E element); //將指定位置的元素移除 E remove(int index); //返回一個元素在集合中首次出現的位置 int indexOf(Object o); //返回一個元素在集合中最後一次出現的位置 int lastIndexOf(Object o); //ListIterator繼承於Iterator,主要增長了向前遍歷的功能 ListIterator<E> listIterator(); //從指定位置開始,返回一個ListIterator ListIterator<E> listIterator(int index); //返回一個子集合[fromIndex, toIndex),非結構性的修改返回值會反映到原表,反之亦然。 //若是原表進行告終構修改,則返回的子列表可能發生不可預料的事情 List<E> subList(int fromIndex, int toIndex);
經過以上對接口的分析能夠發現,Collection
主要提供一些通用的方法,而List
則針對線性表的結構,提供了對位置以及子表的操做。工具
有了分析AbstractCollection
的經驗,咱們分析AbstractList
就更容易了。首先也看下其文檔中強調的部分:學習
To implement an unmodifiable list, the programmer needs only to extend this class and provide implementations for the get(int) and size() methods.ui
To implement a modifiable list, the programmer must additionally override the set(int, E) method (which otherwise throws an UnsupportedOperationException). If the list is variable-size the programmer must additionally override the add(int, E) and remove(int) methods.this
大體意思是說,要實現一個不可修改的集合,只須要複寫get
和size
就能夠了。要實現一個能夠修改的集合,還須要複寫set
方法,若是要動態調整大小,就必須再實現add
和remove
方法。線程
而後看下其源碼實現了哪些功能吧:code
//在AbstractCollection中,add方法默認會拋出異常, //而在這裏是調用了add(int index, E e)方法,但這個方法也是沒有實現的。 //這裏默認會把元素添加到末尾。 public boolean add(E e) { add(size(), e); return true; } //同上,這個只須要進行一次遍歷便可 public boolean addAll(int index, Collection<? extends E> c) { //... }
接下來,還有幾個方法和Iterator
與ListIterator
息息相關,在AbstractList
中有具體的實現,咱們先看看它是如何把集合轉變成Iterator
對象並支持foreach
循環的吧。
咱們追蹤源碼發現,在iterator()
方法中直接返回了一個Itr
對象
public Iterator<E> iterator() { return new Itr(); }
這樣咱們就明白了,它是實現了一個內部類,這個內部類實現了Iterator
接口,合理的處理hasNext
、next
、remove
方法。這個源碼就不粘貼啦,其中僅僅在remove
時考慮了一下多線程問題,有興趣的能夠本身去看看。
另一個就是ListIterator
,
public ListIterator<E> listIterator() { return listIterator(0); }
能夠看到,listIterator
方法依賴於listIterator(int index)
方法。有了上邊的經驗,咱們能夠推測,它也是經過一個內部類完成的。
public ListIterator<E> listIterator(final int index) { rangeCheckForAdd(index); return new ListItr(index); }
事實證實,和咱們想的同樣,AbstractList
內部還定義了一個ListItr
,實現了ListIterator
接口,其實現也很簡單,就不粘貼源碼啦。
接下來咱們看看,利用這兩個實現類,AbstractList
都作了哪些事情。
//尋找一個元素首次出現的位置,只須要從前日後遍歷,找到那個元素並返回其位置便可。 public int indexOf(Object o) { 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(); } return -1; } //同理,尋找一個元素最後一次出現的位置,只須要從列表最後一位向前遍歷便可。 //看到listIterator(int index)方法是能夠傳遞參數的,這個我想咱們均可以照着寫出來了。 public int lastIndexOf(Object o) { //... } //這個方法是把從fromIndex到toIndex之間的元素從集合中刪除。 //clear()方法也是調用這個實現的(我認爲clear實現意義並不大,由於在其上級AbstractCollection中已經有了具體實現)。 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(); } }
接下來還有兩塊內容比較重要,一個是關於SubList
的,一個是關於equals
和hashcode
的。
咱們先看看SubList
相關的內容。SubList
並非新建了一個集合,只是持有了當前集合的引用,而後控制一下用戶能夠操做的範圍,因此在接口定義時就說明了其更改會直接反應到原集合中。SubList
定義在AbstractList
內部,而且是AbstractList
的子類。在AbstractList
的基礎上增長了對可選範圍的控制。
equals
和hashcode
的實現,也關乎咱們的使用。在AbstractList
中,這兩個方法不只與其實例有關,也和其內部包含的元素有關,因此在定義數據元素時,也應該複寫這兩個方法,以保證程序的正確運行。這裏看下其源碼加深一下印象吧。
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(); //這裏用到了數據元素的equals方法 if (!(o1==null ? o2==null : o1.equals(o2))) return false; } return !(e1.hasNext() || e2.hasNext()); }
public int hashCode() { int hashCode = 1; for (E e : this) //這裏用到了數據元素的hashCode方法 hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); return hashCode; }
【感謝您能看完,若是可以幫到您,麻煩點個贊~】
更多經驗技術歡迎前來共同窗習交流: 一點課堂-爲夢想而奮鬥的在線學習平臺 http://www.yidiankt.com/
![關注公衆號,回覆「1」免費領取-【java核心知識點】]
QQ討論羣:616683098
QQ:3184402434
想要深刻學習的同窗們能夠加我QQ一塊兒學習討論~還有全套資源分享,經驗探討,等你哦!