迭代器
迭代器设计模式
封装遍历
- 提供一种方法顺序访问一个聚合对象中的各个元素
- 不暴露对象内部表示
创建一个实现Iterator接口的类(JAVA集合类已经有实现)
组合模式中的迭代器
数个对象集合,有整体/部分关系,考虑用组合模式
https://blog.csdn.net/sophie_su_su/article/details/89635737
JAVA中的迭代器
Iterator接口用于遍历(迭代访问)集合元素。隐藏了各种Collection实现类的底层细节,提供遍历Collection集合元素的统一编程接口。
使用容器的iterator()方法返回一个实现了Iterator接口的类的实例(对象),接口里定义方法next(),hasNext(),remove()
JDK5引入for/in
Java5新增for(Object obj: collection){…}可以在集合或数组中遍历,不用显示创建迭代器
但是不能用索引,如arr[i]
JDK8引入流(外部迭代和内部迭代)
集合和流的一个关键区别在于它们遍历数据的方式。
使用Collection接口需要用户去做迭代(比如用for-each),这称为外部迭代。
而Stream库使用内部迭代 ----- 它帮你把迭代做了,还把得到的流值存在了某个地方,只要给出一个函数说要干什么就可以了。
stream迭代可以发挥多核优势,可以并行处理,而不像外部迭代需要串行处理。
//外部迭代
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Student stu = iterator.next();
if (stu.getSex().equals("G")) {
System.out.println(stu.toString());
}
}
//内部迭代
list.stream()
.filter(student -> student.getSex().equals("G"))
.forEach(student -> System.out.println(student.toString()));
快速失败(fail-fast)和安全失败(fail-safe)的区别?
Iterator的安全失败是基于对底层集合做拷贝,因此,它不受源集合上修改的影响。java.util.concurrent包下面的所有的类都是安全失败的。(concurretHashMap,通过volatile修饰的modcount变量实现,迭代器初始化时,将该值赋给expectmodcount,修改map会增加这个值,不等则说明被修改)
快速失败的迭代器会抛出ConcurrentModificationException异常,(同步修改异常:遍历一个集合时集合结构被修改)而安全失败的迭代器永远不会抛出这样的异常。java.util包下面的所有的集合类都是快速失败的。(synchronizedList)
Iterator和ListIterator的区别?
Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
Enumeration接口和Iterator接口的区别?
优先使用迭代器,两者可以通过适配器互换
Iterator0允许调用者删除底层集合里面的元素, Enumeration不能。
Enumeration(枚举、过时)速度是Iterator的2倍,同时占用更少的内存。
Iterator比Enumeration安全,因为其他线程不能够修改正在被iterator遍历的集合里面的对象。