Iterator 是一种接口。其中定义了hasNext()和next()还有remove()方法 ,每种集合<容器>都有其具体实现。
public interface Iterator{ E next(); boolean hasNext(); void remove(); }
比如ArrayList中的具体实现: 一言不合上源码
public interface Inteator { boolean hasNext(); Object next(); } public interface Iterable { Iterator iterator(); } //Iterable接口里封装了Iterator接口。 public interface Collection extends Iterable { Iterator iterator(); } //注意此处collection是继承的Iterable接口 public interface List extends Collection { Iterator iterator(); } public class ArrayList implements List { public Iterator iterator() { return new Itr(); //返回值是内部类的一个对象(迭代器) } //看这里!定义了一个内部类,来实现接口。 private class Itr implements Iterator { public boolean hasNext() {} public Object next(){} } }
Iterator与Iterable的区别:
在上面的源码中可以看出,Iterable接口中封装着Iterator方法。所以实现了Iterable就是实现了Iterator。而collection是继承的Iterable接口,其实现类中,必须要实现Iterable接口中的方法,也就是实现这个Iterator对象。对于这点,源码中定义了一个内部类将指针和方法封装了起来。
Iterator为什么要用Iterable封装起来呢?
如果直接让collection继承Iterator,那么势必要在ArrayList中实现next();,hasNext();方法。可是为了实现这两个方法,就必须要定义一个指针作为成员变量,来指向当前迭代位置。这个问题就大了,假设我们需要在集合中定义两个方法,其中都包括迭代器,两个方法偏偏都需要我们从头计数。那么根据定义,作为成员变量的指针,一旦对象创建后,指针的指向会随着不同方法的调用,而改变指向,从而无法从头计数,除非再编写一个重置函数。所幸,Iterable可以解决这个问题。他封装好了Iterator对象,每次调用iterator方法就会返回一个新的迭代器。
有关Iterator()迭代过程中出现的异常问题:
使用iterator()方法时经常会遇到ConcurrentModificationException异常。为什么会出现这种问题呢?
1. 单线程在使用迭代器遍历集合的过程中,对集合中的元素进行增删操作
2. 出现多线程操作,一个线程使用迭代器遍历,另一个线程在增加或删除集合对象。
关于问题一如何解决:
在遍历的过程中,遇到想要删除的元素,就先放在其他一个集合里,等遍历完了,用removeAll(collection e) 一次解决。 那么如何增加呢?----还没想到
Iterator怎么识别的呢? 调用Iterator()之时,迭代器产生一个expectedModCount变量<最初的对象个数>,每次调用next()方法会和容器中实际的modcount进行比较,看看是否相等,不等就返回异常。
至于问题二,多线程问题怎么解决:
1)在JDK1.5版本引入了线程安全的容器,比如ConcurrentHashMap和CopyOnWriteArrayList等。可以使用这些线程安全的容器来代替非线程安全的容器。
2)在使用迭代器遍历容器时对容器的操作放到synchronized代码块中,但是当引用程序并发程度比较高时,这会严重影响程序的性能。
关于几种遍历方式总结:
foreach:实现了Iterable接口就能够用
next():在源码里可以看见是用的get(i)的方式。
现在是午夜1点半,终于要对Iterator说晚安啦~ 文中有个问题没解决,最后还有各种遍历方式木有写,明天就补上。
内心OS: 大佬 help me!