了解迭代器

迭代器模式

就是提供一种方法对一个容器对象中的各个元素进行访问,而又不暴露该对象容器的内部细节

比如对于数据的遍历

1
2
3
4
int array[] = new int[3];    
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}

对ArrayList的处理

1
2
3
4
5
6
7
8
9
10
11
12
List<String> list = new ArrayList<String>();
for(int i = 0 ; i < list.size() ; i++){
String string = list.get(i);
}
```
对于这两种方式,我们知道他的内部结构,访问集合和集合本身是紧密耦合的,无法将访问逻辑和集合代码分离出来,不同的集合对应不同的访问方法,但是**Iterator**,它总是用同一种逻辑来遍历集合,集合的内部状态由Iterator来维护,客户端不用直接和集合打交道

### Iterable接口

Iterable接口实现的功能是返回一个迭代器,该接口的iterator()方法返回一个标准的Iterator实现,实现Iterable接口允许对象成为Foreach语句的目标,就可以用过foreach语句来遍历你的底层序列

看看JDK8中定义的Iterable接口

public interface Iterable {

//返回一个迭代器
Iterator iterator();

default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}

default Spliterator spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}

1
2
3

iterator方法返回一个Iterator接口 ,我们看看Iterator接口:

public interface Iterator {

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());
}

1
简单实现一个迭代器:

public class Test {

public static void main(String[] args) {
    ReverseList<String> list=new ReverseList();

    list.add("111");
    list.add("222");
    list.add("333");

    Iterator<String> iterator = list.iterator();

    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}

}

class ReverseList implements Iterable {

private List<T> list = new ArrayList<>();

public void add(T data) {
    list.add(data);
}


@Override
public Iterator<T> iterator() {
    return new ReverIterator(list.size());
}

private class ReverIterator implements Iterator<T> {

    int index;

    ReverIterator(int size) {
        this.index = size;
    }

    @Override
    public void remove() {
        list.remove(index);
    }

    @Override
    public boolean hasNext() {
        return index>0;
    }

    @Override
    public T next() {
        index--;
        return list.get(index);
    }
}

}

1
2
3
4

### 遍历元素

Java8为Iterable接口新增了一个forEach(Consumer action)方法,查看源码,其内部也是使用的 for each遍历,在上面的例子中,我们使用Foreach遍历

ReverseList list=new ReverseList();
list.add(“111”);
list.add(“222”);
list.add(“333”);

    list.forEach(x-> System.out.println(x));
1
2
3
4
也将得出反序的元素输出

Java8为iterator新增的默认forEachRemaining方法,该方法可以用lamdba遍历集合

ReverseList list=new ReverseList();
list.add(“111”);
list.add(“222”);
list.add(“333”);
Iterator iterator = list.iterator();
iterator.forEachRemaining(x-> System.out.println(x));


### 快速失败机制
当使用Iterator迭代访问Collection集合元素时,Collection集合里的元素不能被改变(**只有改变集合个数才会引发,使用list.set(index,element)方法改变某个元素时不会引发**),只有通过Iterator的remove()方法删除上一次next()方法返回的集合元素才可以,否则将会引发ModificationException异常.    







本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!