List(有序的集合)
- List使用一個(gè)數(shù)組來(lái)持有元素,可以在任意位置插入或刪除元素,也可以通過(guò)索引訪問(wèn)任意位置的元素。
- List允許插入重復(fù)的元素,若List的實(shí)現(xiàn)支持null還可以插入多個(gè)null元素。
- 為了方便在List中又重復(fù)聲明了Collection中的接口
- List還定義了一個(gè)ListIterator的迭代器,支持雙向訪問(wèn)、插入和修改元素,并可以從任意位置處開(kāi)始迭代。
- List定義了兩個(gè)查找指定對(duì)象的接口,但這個(gè)查找是線(xiàn)性查找效率并不高。
- 試圖查找一個(gè)不存在的元素時(shí)有的List實(shí)現(xiàn)會(huì)拋出異常有的則會(huì)返回false。
一、List接口
public interface List<E> extends Collection<E> {
// ...
}
1.1 增
1.1.1 booxlean add(E e)
將元素添加到List的末尾。有的List可能會(huì)對(duì)元素的類(lèi)型做限制如不允許添加null。
1.1.2、 void add(int index, E element);
將元素添加到指定位置,原位置以及后面的元素右移。
1.1.3、 boolean addAll(Collection<? extends E> c)
將集合c中所以元素按iterator的返回順序添加到List的末尾。
該方法不是線(xiàn)程安全的若在進(jìn)行此操作的同時(shí)其他線(xiàn)程修改了List那么該操作的結(jié)果是不確定的。
1.14、 boolean addAll(int index, Collection<? extends E> c);
將集合c的所有元素按Iterator的返回順序添加到index開(kāi)始處,index及后面的元素右移。
該方法不是線(xiàn)程安全的若在進(jìn)行此操作的同時(shí)其它線(xiàn)程修改了List那么該操作的結(jié)果是不確定的。
1.2、刪
1.2.1、 boolean remove(Object o)
將指定元素從List中移除(可選)。若元素存在則移除并返回true。
若元素在List中存在多個(gè)則移除第一個(gè)即index最小的一個(gè)。
1.2.2、E remove(int index);
移除指定位置的元素并將其返回。
移除后后面的元素左移。
1.2.3、 boolean removeAll(Collection<?> c);
將存在于集合c中的所有元素刪除。
若有元素被移除則返回true。
1.2.4、 boolean retainAll(Collection<?> c)
刪除所有未在集合c中存在的元素。
若有元素被移除則返回true
1.3、查
1.3.1、 boolean contains(Object o)
判斷元素在List中是否存在,若在集合中至少存在一個(gè)與o相等的元素則返回true。
一般判斷元素是否相等:(o==null ? e==null : o.equals(e))
1.3.2、 boolean containsAll(Collection<?> c)
若List中包含指定集合的所有元素則放回true。
1.3.3、 E get(int index)
返回index處的元素,若“ndex < 0 || index >= size()”拋出IndexOutOfBoundsException異常。
1.3.4、 int indexOf(Object o)
返回指定元素的在List中最小的的index。若List中不存在指定元素則返回-1。
1.3.5、 int lastIndexOf(Object o);
返回指定元素的在List中的最后index(即最大的)。若List中不存在指定元素則返回-1.
1.3.6、 Iterator<E> iterator()
返回順序的List迭代器
1.3.7、ListIterator<E> listIterator()
返回List的ListIterator迭代器
1.3.8、ListIterator<E> listIterator(int index)
返回從index開(kāi)始的ListIterator,獲取到ListIterator后第一次調(diào)用next或previous返回的是index處的元素。
1.3.8、 List<E> subList(int fromIndex, int toIndex)
放回從fromIndex(包括)開(kāi)始到toIndex(不包括)的子List,對(duì)返回的子List的操作會(huì)影響到源List。
1.4、改
1.4.1、 E set(int index, E element)
將指定位置處的元素替換為指定元素并返回之前的元素。
1.4.2、default void replaceAll(UnaryOperator<E> operator)
用指定的UnaryOperator對(duì)所有元素進(jìn)行更新。
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
1.5、其它
1.5.1、 int size()
返回List的大小,若超過(guò)Integer.MAX_VALUE則返回Integer.MAX_VALUE。
1.5.2、 boolean isEmpty()
若集合中一個(gè)元素都沒(méi)有則返回true。
1.5.3、boolean equals(Object o)
當(dāng)且僅當(dāng)o也是List且o的大小與該List大小相等,并且兩個(gè)List中的所有元素相等時(shí)放回true。
1.5.4、int hashCode()
List的hashCode,List建議List的hashCode使用以下方式生成。這樣保證List的equals相等時(shí)hashCode也是相等的。
int hashCode = 1;
for (E e : list)
hashCode = 31 * hashCode + (e==null ? 0 : e.hashCode());
}
二、AbstractList
AbstractList實(shí)現(xiàn)了一些List的通用的默認(rèn)方法,同時(shí)定義了用來(lái)遍歷List的Iterator和ListIterator的迭代類(lèi)。
在AbstractList中定義了一個(gè)記錄List修改次數(shù)的變量,在每次變更List時(shí)都會(huì)加1,在通過(guò)Iterator或ListIterator遍歷List時(shí)會(huì)比較修改次數(shù)是否與遍歷開(kāi)始時(shí)相同,若不同則會(huì)拋出ConcurrentModificationException異常。所以各個(gè)List的在遍歷是都不能使用List直接修改,但可以使用Iterator進(jìn)行修改。
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
// 修改次數(shù)
protected transient int modCount = 0;
}
2.1 boolean add(E e)
將元素添加到List的末尾。調(diào)用添加到指定位置的add(int, E)實(shí)現(xiàn),但AbstractList并未實(shí)現(xiàn)添加到指定位置的add。
public boolean add(E e) {
add(size(), e);
return true;
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
2.2 int indexOf(Object o)
查詢(xún)?cè)卦贚ist中首次出現(xiàn)的位置。通過(guò)listIterator迭代器逐個(gè)遍歷比較,若不存在則返回-1。
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;
}
2.3 int lastIndexOf(Object o)
查詢(xún)?cè)卦贚ist中最后出現(xiàn)的位置。通過(guò)listIterator(size())獲取從末尾開(kāi)始的迭代器然后previous向前逐個(gè)遍歷比較。
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;
}
2.4 public void clear()
通過(guò)removeRange清空范圍的List從而清空List。
public void clear() {
removeRange(0, size());
}
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();
}
}
2.5 boolean addAll(int index, Collection<? extends E> c)
將集合中的元素添加到index開(kāi)始處。通過(guò)遍歷集合調(diào)用add(int, Objet)逐個(gè)添加
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;
}
2.6 Iterator<E> iterator()
Itr是在AbstractList中定義的一個(gè)迭代器,從0處開(kāi)始遍歷。
public Iterator<E> iterator() {
return new Itr();
}
2.7 ListIterator<E> listIterator()
ListItr是在AbstractList中實(shí)現(xiàn)的一個(gè)ListIterator,支持前后遍歷默認(rèn)從0處開(kāi)始遍歷。
public ListIterator<E> listIterator() {
return listIterator(0);
}
public ListIterator<E> listIterator(final int index) {
rangeCheckForAdd(index);
return new ListItr(index);
}
2.8 boolean equals(Object o)
判斷l(xiāng)ist是否相等,若指定元素是List、數(shù)量相等且按listIterator返回的順序元素都相等則返回true
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());
}
三、Itr
在AbstractList中定義了一個(gè)List的迭代器內(nèi)部類(lèi)Itr。Itr從0處開(kāi)始逐個(gè)遍歷到size處。
創(chuàng)建Itr時(shí)Itr會(huì)記住當(dāng)前List的修改次數(shù),在迭代元素時(shí)會(huì)比較List的當(dāng)前修改次數(shù)與Itr記錄的次數(shù)是否相等,若不等則拋出ConcurrentModificationException異常。所以在使用Iterator遍歷List時(shí)不能通過(guò)List提供的方法去改變List。
Iterator定義了remove接口,在Itr中也實(shí)現(xiàn)了該接口。Itr的reomve方法時(shí)安全的,因?yàn)樵诿看握{(diào)用Itr的remove時(shí)Itr都會(huì)重新同步List的當(dāng)前修改次數(shù),這樣在調(diào)用Itr的remove后繼續(xù)通過(guò)Itr遍歷List是安全的。
private class Itr implements Iterator<E> {
// 初始在0處
int cursor = 0;
// 最后返回的元素index
int lastRet = -1;
// 保存當(dāng)前的修改次數(shù)
int expectedModCount = modCount;
// cursor一直遍歷到seize()-1處
public boolean hasNext() {
return cursor != size();
}
// 使用get(i)獲取元素,然后cursor加1。
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
// 刪除前先判斷修改次數(shù)是否一一致,一致則調(diào)用AbstractList的remove方法。修改后會(huì)更新修改次數(shù),所以使用Iterator的remvoe是安全的。
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
// 每次迭代時(shí)都會(huì)調(diào)用該方法比較修改次數(shù)是否有變化
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
四、ListIterator
List擴(kuò)展了一個(gè)支持前后遍歷、插入和修改的ListIterator迭代器,ListIterator繼承自Iterator。ListIterator沒(méi)有當(dāng)前元素,它的index在previous()和next()之間。List是基于數(shù)組的,對(duì)此ListIterator也提供了元素在數(shù)組中位置的相關(guān)的接口。ListIterator新增的接口:
public interface ListIterator<E> extends Iterator<E> {
/*
* 將元素插入到List中,新元素將插入到next返回的元素之前previous返回的元素之后。
* 新插入元素后next調(diào)用不受影響,調(diào)用previous()將返回新插入的元素.
* set和add方法不是對(duì)當(dāng)前index處的元素,而是針對(duì)previous或next最后放回的元素。
*/
void add(E e);
// 如果反向遍歷還有元素則返回true
boolean hasPrevious();
// 返回上一個(gè)元素,同時(shí)index向前移動(dòng)。調(diào)用previous后再調(diào)用next則會(huì)返回相同的元素。
E previous();
// 返回下一次next調(diào)用返回的元素的index。
int nextIndex();
// 返回下一次previous調(diào)用返回的元素的index。
int previousIndex();
// 刪除上一次next或previous調(diào)用返回的元素。只能再進(jìn)行next或previous調(diào)用后進(jìn)行移除remove()調(diào)用。如果上傳調(diào)用next或previous后又調(diào)用了add則不可以調(diào)用remove。
void remove();
// 將最后next或previous返回的元素更新未指定元素。如果next或previous后調(diào)用了add或remove方法則不可調(diào)用set。
void set(E e);
}
ListItr
在AbstractList中定義了一個(gè)的默認(rèn)ListIterator迭代器ListItr的內(nèi)部類(lèi)。需要指定開(kāi)始的位置。
private class ListItr extends Itr implements ListIterator<E> {
// 創(chuàng)建時(shí)要指定開(kāi)始的位置
ListItr(int index) {
cursor = index;
}
// 返回上一個(gè)元素,先檢查是在遍歷期間是否進(jìn)行了修改
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();
}
}
// 下一個(gè)元素的index
public int nextIndex() {
return cursor;
}
// 上一個(gè)元素的index
public int previousIndex() {
return cursor-1;
}
// 更新最后一個(gè)返回的元素,更新后也更新修改次數(shù),所以ListIterator的set調(diào)用是安全的,單List的set調(diào)用或在對(duì)ListIterator進(jìn)行調(diào)用就會(huì)拋出異常。
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();
}
}
// 在previous和next間添加一個(gè)元素。添加后修改ListIterator的修改次數(shù),所以通過(guò)ListIterator調(diào)用add方法是安全的。
public void add(E e) {
checkForComodification();
try {
int i = cursor;
AbstractList.this.add(i, e);
lastRet = -1;
cursor = i + 1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}