迭代器模式UML类图
实现代码如下(这里使用的集合是list,也可以使用其他集合这里就不一一展示了)
public interface Iterator<T> {
T next();
boolean hasNext();
}
复制代码
public class ConcreteIterator<T> implements Iterator<T>{
private final List<T> list;
private int cursor = 0;
public ConcreteIterator(List<T> list){
this.list = list;
}
@Override
public T next() {
if(hasNext()) {
return list.get(cursor++);
}
return null;
}
@Override
public boolean hasNext() {
return list.size() > cursor;
}
}
复制代码
public interface IAggregate {
void add(User user);
void remove(User user);
Iterator<User> iterator();
}
复制代码
public class ConcreteAggregate implements IAggregate{
private final List<User> users = new ArrayList<>();
@Override
public void add(User user) {
users.add(user);
}
@Override
public void remove(User user) {
users.remove(user);
}
@Override
public Iterator<User> iterator() {
return new ConcreteIterator<>(users);
}
}
复制代码
public class Test {
public static void main(String[] args) {
User user1 = new User("张三", "123");
User user2 = new User("张三2", "123");
User user3 = new User("张三3", "123");
User user4 = new User("张三4", "123");
User user5 = new User("张三5", "123");
User user6 = new User("张三6", "123");
User user7 = new User("张三7", "123");
ConcreteAggregate concreteAggregate = new ConcreteAggregate();
concreteAggregate.add(user1);
concreteAggregate.add(user2);
concreteAggregate.add(user3);
concreteAggregate.add(user4);
concreteAggregate.add(user5);
concreteAggregate.add(user6);
concreteAggregate.add(user7);
Iterator<User> iterator = concreteAggregate.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toString());
}
}
}
复制代码
看完这些代码后可能有些人会说直接for循环不是很简单,的确很多时候for循环的确很简单,但是遇到上文中的删除操作那你的for循环是不是会有点问题,当然还有人说这个问题很好解决。当你遇到的集合是树、图再用for循环是不是很复杂,而且你的业务中有很多这样的结构的时候你的for循环是不是到处都是,如果我们写一个迭代器,复杂遍历逻辑放到迭代器里面使用到的地方只需要调用岂不是很方便,代码也相对更优雅一些
迭代器在源码中的应用
我们知道java中的集合最终都会实现Iterable
接口如下图所示:
我们可以看一下Iterable
源码
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
复制代码
发现这里就会回了迭代器再看 Iterator
源码
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
复制代码
发现和上文中定义的几乎一样 这里我们可以看一下迭代器的具体实现(这里拿List举例)
发现具体实现类是 ListItr
再看源码:
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
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(e);
}
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor-1;
}
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();
}
}
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();
}
}
}
复制代码
这里面就实现了List的遍历
迭代器模式的优缺点
优点:
- 多态迭代:为不同的聚合结构提供一致的遍历接口,即一个迭代接口可以访问不同的集合对象
- 简化集合对象接口:迭代器模式将集合对象本身应该提供的元索迭代接口抽取到了迭代器 中,使集合对象无须关心具体迭代行为
- 元素迭代功能多样化:每个集合对象都可以提供一个或多个不同的迭代器,使的同种元素聚 合结构可以有不同的迭代行为;
- 解耦迭代与集合:迭代器模式封装了具体的迭代算法,迭代算法的变化,不会影响到集合 对象的架构
缺点:
对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐。