1. 程式人生 > >java List介面 及 Iterator和ListIterator的區別

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

        http://www.monkey1024.com/javase/540