Java基础_迭代器iterator
一、 迭代器的使用
在Java中,有很多的数据容器,对于这些的操作有很多的共性。Java采用了迭代器来为各种容器提供了公共的操作接口。这样使得对容器的遍历操作与其具体的底层实现相隔离,达到解耦的效果。
1. Iterator接口
//代码1
public static void main(String[] args)
{
List<String> list=new ArrayList<>();
list.add("abc");
list.add("edf");
list.add("ghi");
for(Iterator<String> it=list.iterator();it.hasNext();)
{
System.out.println(it.next());
}
}
二、ArrayList 中的Iterator实现
- cursor: 表示下一个元素的索引位置
- lastReturn:表示上一个元素的索引位置
- expectedModCount: 预期被修改的次数
hasNext()的实现
next()的实现
在其中调用了checkRorComdification();方法判断集合结构是否发生了改变。(快速失败)
checkRorComdification()方法,判断集合是否发生改变
- 在集合内部维护了一个字段 modCount来记录集合被修改的次数,如果几个内部结构发生了改变(add,remove,set 操作会对modCount ++)
- 在迭代器内部也维护一个字段expectedModCount,同样记录当前集合修改的次数,初始化为集合的modCount值。当我们在调用Iterator进行遍历操作时,如果有其他线程修改list会出现modCount!=expectedModCount的情况,就会报并发修改异常java.util.ConcurrentModificationException。
报错代码如下:
//代码2:迭代器内删除
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add(i);
}
System.out.println("移除前:" + list);
Iterator<Integer> it = list.iterator();
Integer temp;
while (it.hasNext()) {
if ((temp = it.next()) % 2 == 0) {
list.remove(temp);
}
}
System.out.println("移除后:" + list);
}
运行结果:
应该使用迭代器中的来进行删除(Iterator中只提供了remove方法)才可以。
代码如下:
//代码3:使用迭代器中的remove
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add(i);
}
System.out.println("移除前:" + list);
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
if (it.next() % 2 == 0) {
it.remove();
}
}
System.out.println("移除后:" + list);
}
三、 ListIterator
- 上面可以看到,Iterator只提供了删除元素的方法remove,如果我们想要在遍历的时候添加元素怎么办
- ListIterator接口继承了Iterator接口,它允许程序员按照任一方向遍历列表,迭代期间修改列表,并获得迭代器在列表中的当前位置。
- ListIterator接口定义了下面几个方法:
四、foreach
- foreach 可以遍历基于 iteration 和下标遍历的内部实现。Java编译器对Java语言对其实现做了隐藏。
基于 iteration: 编译器底层会调用Iterable接口的 iterator方法来循环遍历数组的元素;
基于下标遍历: Java将对于数组的foreach循环转换为对于这个数组每一个的循环引用;