一、Iterator简介:
1、java.util.Iterator为一个接口,它只提供了迭代了基本规则,提供一种方法访问某个容器(container)对象中的各个元素,而又不需暴露该对象的内部细节/底层结构。在 JDK 中他是这样定义的:对collection 进行迭代的迭代器。从定义可见,Iterator(迭代器)模式又叫做Cursor(游标)模式是为容器而生。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免2、向客户端暴露集合的内部结构。
2、迭代其实我们可以简单地理解为遍历,是遍历各类容器里面的所有对象的标准访问方法,它是一个很典型的设计模式。很明显,对容器对象的访问必然涉及到遍历算法。你可以一股脑的将遍历方法塞到容器对象中去;或者根本不去提供什么遍历算法,让使用容器的人自己去实现去吧。这两种情况好像都能够解决问题。
其源码如下:
package java.util;
public interface Iterator<E>
{
boolean hasNext();
E next();
void remove();
}
二、Iterator用法
Java中的Iterator功能比较简单,并且只能单向向前遍历:
(1)容器调用iterator()要求集合类容器返回一个Iterator对象。注意:好多集合类都实现了java.lang.Iterable接口,这样容器对象就可以调用iterator()方法。
(2)hasNext() 检查容器中是否还有元素。
(3)next() 获得容器中的下一个元素。第一次调用时,它返回容器的第一个元素。
(4)remove() 将迭代器新返回的元素删除。
List<String> strList = new ArrayList<>();
//1、using for-each loop
for(String str : strList)
System.out.println(str);
//2、using iterator
Iterator<String> it = strList.iterator();
while(it.hasNext())
{
String str = it.next();
System.out.println(str);
}
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
三、Fail-Fast(快速失败)机制
我们知道的是ArrayList是线程不安全的,如果在使用迭代器的过程中有其他的线程修改了List就会抛出ConcurrentModificationException这就是Fail-Fast机制,为了防止多线程下迭代的不安全操作。
那么快速失败究竟是个什么意思呢?
在ArrayList类创建迭代器之后,除非通过迭代器自身remove或add对列表结构进行修改,否则在其他线程中以任何形式对列表进行修改,迭代器马上会抛出异常,快速失败。
四、Iterator进阶
枚举是快迭代两倍,使用非常少的内存。枚举适合基本需求。但Iterator是更安全,因为它总是拒绝其他线程修改它正在迭代集合中的对象。
我们可以使用迭代器Iterator遍历Set和List集合,而ListIterator只可以使用List。
迭代器遍历只有向前的方向,而ListIterator可以用来在两个方向遍历。
ListIterator继承Iterator接口,并配备了额外的功能,如添加元素,更换一个元素,能获得上一个和下一个元素的索引位置。
3.fail-fast与fail-safe有什么区别?
Iterator的fail-fast属性与当前的集合共同起作用,因此它不会受到集合中任何改动的影响。Java.util包中的所有集合类都被设计为fail-fast的,而java.util.concurrent中的集合类都为fail-safe的。当检测到正在遍历的集合的结构被改变时,Fail-fast迭代器抛出ConcurrentModificationException,而fail-safe迭代器从不抛出ConcurrentModificationException。
①迭代器可以提供统一的迭代方式。
②迭代器也可以在对客户端透明的情况下,提供各种不同的迭代方式。
③迭代器提供一种快速失败机制,防止多线程下迭代的不安全操作。
五、foreach循环
它能在不使用下标的情况下遍历集数组或容器,foreach将自动产生每一项元素。其基本语法如下:
for(type element:obj)
{
//循环体:含有elemengt的语句块
}
List<String> strList = new ArrayList<>();
strList.add("111");
strList.add("222");
strList.add("333");
for(String str : strList)
System.out.println(str);
2、适用范围:对于任何实现Iterable接口的容器都可以使用foreach循环。foreach语法的冒号后面可以有两种类型:一种是数组,另一种是是实现了Iterable接口的类。
3、For-Each循环的缺点:丢掉了索引信息。
当遍历集合或数组时,如果需要访问集合或数组的下标,那么最好使用旧式的方式来实现循环或遍历,而不要使用增强的for循环,因为它丢失了下标信息。