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

猜你喜欢

转载自blog.csdn.net/sinat_41132860/article/details/84110725