一、Iterator 迭代器方法介绍
- 迭代器
- 迭代器是一种设计模式、提供了一种方法,对集合、容器进行遍历的方式;
- 不需要关注底层数据结构和数据类型,来达到底层和上层遍历解耦的目的;
- Iterator类里有三个方法:
boolean hasNext() //判断集合是否还有元素
E next(); //返回当前数据
void remove(); //删除元素
- 例如使用Iterator遍历ArrayList
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
arrayList.add(Integer.valueOf(random.nextInt(50)));
}
Iterator<Integer> iterator = arrayList.iterator();
while (iterator.hasNext()) {
Integer next = iterator.next();
//iterator.remove();
System.out.print(next + " ");
}
System.out.println();
}
运行结果:
如果调用remove()方法删除遍历过的元素,则:
可以看到集合中的元素都被删掉了;
二、自定义迭代器类:
- 需要具有iterator方法实现Iterable接口;
- 需要实现Iterator接口,重写HasNext()、next()、remove()方法;
例如:
public class DIYArrayList<T> implements Iterable<T> {
/**
*手写的ArrayList在之前文章中提到过
*/
@Override
public Iterator<T> iterator() {
return new Itr();
}
class Itr implements Iterator<T> {
private int cursor = 0;//下一个元素的索引位置
private int lastRet = -1;//上一个元素的索引位置
@Override
public boolean hasNext() {
return cursor != size; //当cursor不等于size时,表示仍有元素
}
@Override
public T next() {
if (cursor > size) {
throw new IndexOutOfBoundsException("");
}
lastRet = cursor;
cursor += 1;
return data[cursor];
}
@Override
public void remove() {
//T next = next();
DIYArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
}
}
测试及结果:
public static void main(String[] args) {
DIYArrayList<Integer> arrayList = new DIYArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
arrayList.add(Integer.valueOf(random.nextInt(50)));
}
Iterator<Integer> iterator = arrayList.iterator();
while (iterator.hasNext()) {
Integer next = iterator.next();
iterator.remove();
System.out.print(next + " ");
}
System.out.println();
System.out.println("调用remove()后集合元素个数: " + arrayList.size);
}
三、并发异常问题 (ConcurrentModificationException)
原因:在源码中可以看到有一个modCount属性,标记的是版本号,而集合本身修改会引起modCount版本号修改,而迭代器本身的版本号并未改变,因此会抛出异常
四、fair-fast机制 (快速失败机制)
fair-fast机制是Java集合(Collection)中的一种错误机制
- 在多线程环境下,当多个线程对同一个集合的内容进行操作时,就可能会产生fair-fast快速失败事件;
- 但是单线程条件下如果违反了规则也会产生快速失败事件
例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程改变了,线程A访问集合时就会抛出ConcurrentModificationException异常,产生快速失败事件;
五、ListIterator
ListIterator继承自Iterator,在Iterator的基础上增加了一些方法;
六、interator和ListIterator的区别与联系
遍历集合 | 添加元素 | 逆序遍历 | 定位当前索引 | 删除对象 | 修改对象 | |
---|---|---|---|---|---|---|
interator | 可以 | 不可以 | 不可以 | 不可以 | 可以 | 不可以 |
ListIterator | 可以 | 可以 | 可以 | 可以 | 可以 | 可以 |
-
都有hasNext()和next()方法,可以实现从前往后遍历;
-
ListIterator有add()方法,可以往集合中添加元素,iterator不能;
-
ListIterator有hasPrevious()和previous方法,可以实现逆序遍历;
-
ListIterator可以通过nextIndex()和previousIndex()方法定位当前索引位置;
-
都有remove()方法实现对象的删除;
-
ListIterator可以通过set()方法实现对象的修改;