List
List
是一個(gè)有序集合的接口,自然就相比Collection
來(lái)說(shuō)就添加了一些和索引有關(guān)的方法:
void add(int index, E element);
boolean addAll(int index, Collection<? extends E> c);
default void sort(Comparator<? super E> c);
E get(int index);
E set(int index, E element);
E remove(int index);
int indexOf(Object o); //若未找到則返回-1
int lastIndexOf(Object o); //若未找到則返回-1
以及一些其他獨(dú)有的方法:
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
default void replaceAll(UnaryOperator<E> operator)
List<E> subList(int fromIndex, int toIndex);
值得一提的是坞淮,在Java 9之后還出了一堆靜態(tài)方法,它們是用來(lái)創(chuàng)建不可修改的List的(也就是生成對(duì)象以后就不能新增和修改其中的元素了)
static <E> List<E> of()
static <E> List<E> of(E e1)
static <E> List<E> of(E e1, E e2)
...
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)
static <E> List<E> of(E... elements)
AbstractList
與AbstractColletion
類似陪捷,它也是系統(tǒng)提供的一個(gè)List
接口的骨干實(shí)現(xiàn)回窘,為了減輕程序員的工作量。如果要實(shí)現(xiàn)不可修改元素的列表市袖,繼承它并實(shí)現(xiàn)get(int)
和size()
方法即可啡直。若要實(shí)現(xiàn)可修改元素的列表,還需要實(shí)現(xiàn)set(int, E)
,add(int, E)
和remove(int)
方法 (如果是長(zhǎng)度不可變的列表的話后兩個(gè)方法也可以不實(shí)現(xiàn))付枫。
它繼承自AbstractColletion
烹玉,也就是說(shuō)它將AbstractColletion
里的iterator
方法給實(shí)現(xiàn)了,不過(guò)這個(gè)方法在本系列第一講中就已經(jīng)介紹過(guò)了hhhh
然后它也實(shí)現(xiàn)了List
接口,將大部分方法給實(shí)現(xiàn)了兔跌。
這些方法都比較簡(jiǎn)單擎析,值得一提的是subList
方法:
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size());
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, toIndex));
}
根據(jù)名字就知道這是用來(lái)生產(chǎn)子列表的。
這里先進(jìn)行防越界檢查事示,然后就是判斷是不是RandomAccess
接口的實(shí)例(這個(gè)接口,根據(jù)文檔解釋,就是用來(lái)表示某個(gè)列表是否支持隨機(jī)訪問(wèn)装获,而不是只支持順序訪問(wèn)),然后再生成SubList
的對(duì)象厉颤。
SubList是個(gè)內(nèi)部類穴豫,繼承自AbstractList
構(gòu)造函數(shù)有兩個(gè):
/**
* Constructs a sublist of an arbitrary AbstractList, which is
* not a SubList itself.
*/
public SubList(AbstractList<E> root, int fromIndex, int toIndex) {
this.root = root;
this.parent = null;
this.offset = fromIndex;
this.size = toIndex - fromIndex;
this.modCount = root.modCount;
}
/**
* Constructs a sublist of another SubList.
*/
protected SubList(SubList<E> parent, int fromIndex, int toIndex) {
this.root = parent.root;
this.parent = parent;
this.offset = parent.offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = root.modCount;
}
分別是用List來(lái)生成SubList,以及用SubList來(lái)生成SubList逼友,支持多層嵌套精肃,也就是說(shuō)SubList的SubList的SubList...這種都可以。還可以看出root是指最最上層的根List帜乞,而parent則是比自己高一級(jí)的SubList司抱。
仔細(xì)看一下其他方法:
public E set(int index, E element) {
Objects.checkIndex(index, size);
checkForComodification();
return root.set(offset + index, element);
}
public E get(int index) {
Objects.checkIndex(index, size);
checkForComodification();
return root.get(offset + index);
}
public void add(int index, E element) {
rangeCheckForAdd(index);
checkForComodification();
root.add(offset + index, element);
updateSizeAndModCount(1);
}
public E remove(int index) {
Objects.checkIndex(index, size);
checkForComodification();
E result = root.remove(offset + index);
updateSizeAndModCount(-1);
return result;
}
可以看出這里的各種增刪查改都是通過(guò)調(diào)用根列表的增刪查改實(shí)現(xiàn)的。除此之外黎烈,在所有操作之前都有調(diào)用checkForComodification
方法习柠,這是不是和Iterator里的很相似hhh
不過(guò)這里是判斷自己的modCount和根列表的modCount是否相等:
private void checkForComodification() {
if (root.modCount != this.modCount)
throw new ConcurrentModificationException();
}
它的作用也和iterator
里的一樣,為了避免外部類偷偷修改了數(shù)組元素的個(gè)數(shù)照棋,從而導(dǎo)致內(nèi)部類中size
屬性無(wú)法得到更新從而出錯(cuò)资溃。
既然如此,那在內(nèi)部類中修改了數(shù)組個(gè)數(shù)之后就需要對(duì)modCount進(jìn)行更新了烈炭,這在updateSizeAndModCount
方法中有具體實(shí)現(xiàn):
private void updateSizeAndModCount(int sizeChange) {
SubList<E> slist = this;
do {
slist.size += sizeChange;
slist.modCount = root.modCount;
slist = slist.parent;
} while (slist != null);
}
大致上來(lái)說(shuō)就是一直往上尋找自己的上一級(jí)SubList溶锭,把他們的modCount和size都給更新了,這樣下次調(diào)用checkForComodification就不會(huì)拋出錯(cuò)誤了梳庆。