单例模式
定义
提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
对于迭代器(Iterator),Java 语言本身就提供了这样一个接口。
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());
}
}
集合类都实现了Iterator接口来对外提供遍历访问,以隐藏集合内部的实现。
public interface Collection<E> extends Iterable<E> {
//...
}
比如要实现ArrayList的遍历操作,
public class Main {
public static void main(String[] args) {
ArrayList<String> lists = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
Iterator<String> iterator = lists.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
应用
自己实现一个集合类,用来存放数据。
public class MyCollection {
private String[] elements;
public MyCollection(String[] elements) {
this.elements = elements;
}
public String[] getElements() {
return elements;
}
public void setElements(String[] elements) {
this.elements = elements;
}
}
然后对它进行遍历的操作。
public void print(MyCollection myCollection) {
String[] elements = myCollection.getElements();
for (int i = 0; i < elements.length; i++) {
System.out.println(elements[i]);
}
}
虽然这样做可以实现遍历的操作,但是它把我们自定义的集合内的存储结构暴露给了外部。同时这个print 方法只支持我们的MyCollection,对于其他的集合比如ArrayList集合就不适用,这样就会造成代码的重复,降低复用性。
public void print(ArrayList<String> lists) {
for (int i = 0; i < lists.size(); i++) {
System.out.println(lists.get(i));
}
}
如果使用迭代器模式来改造他们,遍历的方法就可以被重用。
public class MyCollection{
private String[] elements;
private int cursor = 0;
//....
public Iterator<String> iterator(){
return new Itr();
}
class Itr implements Iterator<String>{
@Override
public boolean hasNext() {
if (cursor >= elements.length || elements[cursor] == null) {
return false;
} else {
return true;
}
}
@Override
public String next() {
if (cursor >= elements.length) {
throw new ConcurrentModificationException();
} else {
return elements[cursor++];
}
}
}
}
这样只要传入一个迭代器到print方法就可以实现遍历方法的统一。
public void print(Iterator iterator) {
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
总结
优点
-
简化了遍历方式,对于对象集合的遍历,还是比较麻烦的,对于数组或者有序列表,我们尚可以通过游标来取得,但用户需要在对集合了解很清楚的前提下,自行遍历对象,但是对于hash表来说,用户遍历起来就比较麻烦了。而引入了迭代器方法后,用户用起来就简单的多了。
-
可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。
-
封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心。
缺点
- 对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,大家可能都有感觉,像ArrayList,我们宁可愿意使用for循环和get方法来遍历集合。