java List介面 及 Iterator和ListIterator的區別
List介面是Collection介面的一個子介面,繼承了Colelction中的方法,同時還有自己的方法
主要有以下幾種
1.void add(int index,object element):在指定索引位置新增元素,新增在中間位置時,後面的元素依次往後移置,新增的位置可以在最後一位,但新增的索引位置不能越界,否則異常IndexOutOfBoundsException
2.Object get(int index):獲取指定位置的元素,索引不能越界,否則報錯IndexOutOfBoundsException
3.Objec remove(int index):刪除指定位置的元素,並返回該位置的元素,索引位置不能越界,否則報錯IndexOutOfBoundsException
4.Object set(int index):將指定位置的元素修改,返回修改之前該位置的元素
,並返回當前位置的舊元素
list介面特有方法的使用示例
import java.util.ArrayList; import java.util.List; import students.Student; public class ListTest01 { public static void main(String[] args) { List l = new ArrayList(); l.add(new Student(12, "張")); l.add(new Student(13, "李")); l.add(2, new Student(14, "趙")); l.add(3, "a"); addTest(l); getTest(l); removeTest(l); setTest(l); } public static void setTest(List l) { // set(int index,Object element) System.out.println(l); Object o5 = l.set(1, "E"); System.out.println(l); System.out.println(o5); // Object o6 = l.set(10, "S");//索引位置超過list長度,報錯IndexOutOfBoundsException } public static void removeTest(List l) { // remove(int index) Object o3 = l.remove(3); System.out.println(o3); // Object o4 = l.remove(8);// 索引位置超過list長度,報錯IndexOutOfBoundsException } public static void getTest(List l) { // get(int index) Object o1 = l.get(1);// 多型,返回值是元素的物件型別 Student s1 = (Student) o1;// 向下轉型,不轉的話也可以呼叫子類toString方法 System.out.println(s1); Object o2 = l.get(4); Student stu1 = (Student) o2;// 向下轉型,不轉的話是Object型別,也可以呼叫子類Student的方法 System.out.println(stu1); // Object o2=l.get(8);//// 索引位置超過list長度,報錯IndexOutOfBoundsException } public static void addTest(List l) { // add(int index,Object element) l.add(4, new Student(15, "劉")); // l.add(7, "d");//索引位置超過list長度,報錯IndexOutOfBoundsException } } out: Student [age=13, name=李] Student [age=15, name=劉] a [Student [age=12, name=張], Student [age=13, name=李], Student [age=14, name=趙], Student [age=15, name=劉]] [Student [age=12, name=張], E, Student [age=14, name=趙], Student [age=15, name=劉]] Student [age=13, name=李]
Iterator和ListIterator的區別
實現了Collection介面的集合類及子類,都有Iterator方法,返回一個實現了Iterator介面的例項。
在List介面及其實現它的子類如ArrayList、LinkedList和Vector的中還有一個ListIterator
在list介面的實現類ArrayList裡,Iterator和ListIterator這兩個內部類的定義如下(LinkedList,Vector中類似)
private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; // prevent creating a synthetic constructor Itr() {} public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } @Override public void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); final int size = ArrayList.this.size; int i = cursor; if (i < size) { final Object[] es = elementData; if (i >= es.length) throw new ConcurrentModificationException(); for (; i < size && modCount == expectedModCount; i++) action.accept(elementAt(es, i)); // update once at end to reduce heap write traffic cursor = i; lastRet = i - 1; checkForComodification(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } /** * An optimized version of AbstractList.ListItr */ private class ListItr extends Itr implements ListIterator<E> { ListItr(int index) { super(); cursor = index; } public boolean hasPrevious() { return cursor != 0; } public int nextIndex() { return cursor; } public int previousIndex() { return cursor - 1; } @SuppressWarnings("unchecked") public E previous() { checkForComodification(); int i = cursor - 1; if (i < 0) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i; return (E) elementData[lastRet = i]; } public void set(E e) { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(lastRet, e); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void add(E e) { checkForComodification(); try { int i = cursor; ArrayList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } }
使用迭代器next()方法獲得的元素是一個集合中對應元素的深拷貝,如果對迭代變數進行修改是不會修改集合中的原資料的。
迭代器Iterator是對真實集合的一個對映,如果要修改迭代器中的元素,迭代器先對對映進行修改,再將對映的改動更新到真實集合資料,反向不成立,因為迭代器知道自己是哪個真實集合資料的對映,而真實集合資料不知道它與哪些對映相關聯,如果在迭代器使用過程中集合修改了自身的資料,那麼使用與它相關聯的迭代器就會報錯,
ListIterator是Iterator的一個子介面,
定義了一個油表指標,在[0,size]之間移動,比如正向遍歷一遍,
List list=new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
ListIterator lit=list.ListIterator();
while(lit.hasnext()){
System.out.println(lit.next())
}
之後,該迭代器中的遊標值變為4,
定義的方法有:
void add(E e) 在遊標指標前面插入一個元素,即如果往後遍歷的情況下,遊標指向的是add(元素)右邊的那個元素
boolean hasNext() 判斷遊標處是否有元素,實現方法是判斷遊標是否等於size,等於size時返回false,即遊標已經超過集合的索引,此方法是繼承子Iterator介面的方法
boolean hasPrevious() 判斷遊標是否有前一個元素,實現方法是遊標是否等於0,
E next() 返回當前遊標處的元素,遊標後移,E previous() 返回當前遊標下的元素,並將遊標向前移動一位
int nextIndex() 返回當前遊標的值,int previousIndex() 返回當前(遊標-1)這個值
void remove() 刪除迭代器最後一次操作的元素,這個元素必須是next()方法或者previous()方法返回的元素,刪除後,後面的元素依次左移一位,遊標也左移一位,因為它指向的那個元素左移了一位,遊標指向的元素不變
void set(E e) 替換一個next()方法或者previous()方法返回的元素,此方法不能用在remove和add之後,因為新增或者刪除元素後遊標不再指向那個返回的物件,就無法修改了,會報錯
示例:
//測試在iterator迭代的時候修改集合元素
public class ListIteratorTest01 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
Iterator it = list.iterator();
// list.remove(2);//此行程式碼報錯,因為在建立迭代器之後修改集合資料,而迭代器不知道,所以報錯
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
}
Iterator it1 = list.iterator();
while (it1.hasNext()) {
String s1 = (String) it1.next();
if (s1.equals("b")) {
// list.add("g");//這兩行程式碼都在迭代器使用過程中,集合對其修改,迭代器卻不知道,所以報錯
// list.remove(2);//ConcurrentModificationException
}
}
Iterator it2 = list.iterator();
while (it2.hasNext()) {
String s2 = (String) it2.next();
if (s2.equals("b")) {
it2.remove();// 呼叫迭代器的方法修改,迭代器自身變化後,再去修改集合中的值
System.out.println(list);
}
}
}
}
out:
a
b
c
d
e
[a, c, d, e]
//測試ListIterator的部分方法,
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
ListIterator iti = list.listIterator();
while (iti.hasNext()) {
String s3 = (String) iti.next();
System.out.println(s3);
if (s3.equals("b")) {
// 將迭代器返回的物件修改,此方法不能用在remove和add之後,
iti.set("k");// list=[a, k, c, d, e]
// 刪除迭代器返回的那個物件,如果被修改,就刪除哪個修改後的物件
iti.remove();// list= [a, c, d, e]
// 迭代器在當前next()方法返回值的值的後面新增元素,再將映像更新到集合中
iti.add("h");//[a, h, c, d, e]
// iti.set("k");
}
}
System.out.println(list);
// 執行完一遍正向遍歷後,遊標值等於6,等於size值,可以反向遍歷
System.out.println("------------");
while (iti.hasPrevious()) {
System.out.print(iti.nextIndex());
System.out.println(iti.previous());
}
}
}
out:
a
b
c
d
e
[a, h, c, d, e]
------------
5e
4d
3c
2h
1a
參考Iterator和集合的對映部分https://blog.csdn.net/japson_iot/article/details/79010998