一、总述
所谓迭代,也就是遍历的意思:将元素一个一个获取出来。它是不依赖索引的,而是通过指针和移动的方式去获取元素。
我们来看一个场景:假设现在有一个长度为10的集合,我就可以获取一个迭代器对象,从头开始,一个一个的获取集合里面的元素,只不过迭代器有一个最大的特点,迭代器是不依赖索引的。
![image-20240425193705968](https://img-blog.csdnimg.cn/img_convert/4b51d2a9100661372f8b0a27941553ee.png)
迭代器在Java中的类是 Iterator
,迭代器是集合专用的遍历方式。
在代码中,我们可以通过 iterator()
获取迭代器的对象,方法就会返回 Iterator
的对象。
Iterator<E> iterator()
:返回迭代器对象,默认指向当前集合的0索引。
然后再利用迭代器里面的两个方法
boolean hasNext()
:判断当前位置是否有元素,有元素返回true
,没有元素返回false
E next()
:获取当前位置的元素,并将迭代器对象移向下一个索引位置
接下来我们一起来看一个小案例。
二、案例
在这里有一个集合,里面存储了十个元素,迭代器的三个方法我也写好了。
先来看第一行:利用集合调用方法,获取到迭代器的对象,默认指向集合的 0索引
。
迭代器对象我们就可以看做下图的 光标 / 指针 / 箭头。
![image-20240425194614245](https://img-blog.csdnimg.cn/img_convert/1036dd37aeaf4bb93fbd08f4530fe06e.png)
然后再利用迭代器的对象调用 hasNext()
判断当前位置是否有元素,如果有元素,方法就会返回 true
,如果没有,方法返回 false
。
可以发现,此时所在 0索引
是有元素的,因此此时这个方法返回 true
。
当这个迭代器的指针指向了最后一个元素的,后面一个位置时,此时就没有元素了,它会返回 false
。
![image-20240425194910498](https://img-blog.csdnimg.cn/img_convert/21316147064e6f96c54e6dfc493df35a.png)
最后再利用迭代器调用 next()
获取元素并移动迭代器。
这个方法做了两件事情:1、获取元素;2、移动指针
例如下图,获取的就是 0索引
的 "三"
,并将指针移动到了下一个索引处。
![2gpbt-ds1o3](https://img-blog.csdnimg.cn/img_convert/85e28550741fbc7244d5d2afe4967a0f.gif)
但是如果我需要获取集合中所有的元素该怎么办呢?
参数我们就可以通过循环来搞定:将 hasNext()
写在循环的判断条件中,如果当前位置有元素,方法返回 true
,然后我们就进入到循环体中获取元素移动指针。
但是如果当前位置没有元素,方法返回 false
,循环直接结束。
![image-20240425195511628](https://img-blog.csdnimg.cn/img_convert/4b68e4e7370c9c8150471894f23d73e5.png)
三、代码实现
首先往集合中添加元素
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
然后获取迭代器对象
迭代器就好比是一个箭头,默认指向集合的0索引处
Iterator<String> it = coll.iterator();
然后利用循环不断的去获取集合中的每一个元素
while(it.hasNext()){
// next方法的两件事情:获取元素并移动指针
String str = it.next();
System.out.println(str);
}
四、细节
1、迭代器已经指向了最后一个元素的后一个位置,此时你还再次调用 next()
去获取元素的话,那么它会报 NoSuchElementException(没有这个元素异常)
![image-20240425200711710](https://img-blog.csdnimg.cn/img_convert/3c646df54817e334af6f77a760ae59a5.png)
![image-20240425201501516](https://img-blog.csdnimg.cn/img_convert/30ffac07c2e2ca71efd770be81d575dc.png)
但是它为什么报的是 NoSuchElementException
而不是索引越界异常呢?
因为迭代器在遍历的时候,是不依赖索引的,因此它没有报索引越界异常,而是 NoSuchElementException
2、迭代器遍历完成,指针是不会复位的
如果你还想将这个集合再次遍历一遍,需要重新再去获取一个迭代器的对象
第二次获取的时候,拿到的就是一个新的迭代器对象。
Iterator<String> it2 = coll.iterator();
while(it2.hasNext()){
String str = it2.next();
System.out.println(str);
}
3、循环中只能用一次 next()
,如果你想多次使用到当前遍历的元素,就只能先用一个变量去记录,在下面直接使用变量就行了。
hasNext()
和 next()
这两个方法需要配套使用,并且在使用的时候是一一对应的。
String str = it.next();
System.out.println(str);
4、迭代器遍历的时候,不能用集合的方法进行增加或者删除。
Iterator<String> it = coll.iterator();
while(it.hasNext()){
String str = it.next();
if("bbb".equals(str)){
coll.remove("bbb"); // 这个就是用集合的方法进行删除
}
}
System.out.println(coll);
此时就会报 ConcurrentModificationException(并发修改异常)
,它出现的原因就是:在迭代器遍历的时候,如果用集合的方法添加 / 删除,都会报这个错。
![image-20240425203009077](https://img-blog.csdnimg.cn/img_convert/6fed5bbf1e18d649d84da3ffe72f6ebf.png)
那如何解决这种错误呢?打开一下帮助文档,我们需要来查看 Iterator
中还有哪些方法
可以发现在迭代器中,它提供了三个方法,其中第三个 remove()
就可以删除当前获取到的元素。
因此如果需要在遍历的时候进行删除,就不能使用集合中的方法进行删除,而是需要使用迭代器中的方法进行删除。
程序运行完毕,可以发现 "bbb"
已经成功被删掉了。
Iterator<String> it = coll.iterator();
//3.利用循环不断的去获取集合中的每一个元素
while(it.hasNext()){
//4.next方法的两件事情:获取元素,并移动指针
String str = it.next();
if("bbb".equals(str)){
it.remove();
}
}
System.out.println(coll); // [aaa, ccc, ddd, eee]
在遍历的过程中,不可以使用集合的方法进行增加 / 删除,但是当集合遍历完成后,就可以使用集合的方法进行增加 / 删除。
五、总结
1、迭代器在遍历集合的时候是不依赖索引的
它是通过创建指针,并且移动指针的方式去获取到集合中的每一个元素。
2、迭代器需要掌握的三个方法
Iterator<String> it = coll.iterator();
while(it.hasNext()){
String str = it.next();
System.out.println(str);
}
3、迭代器的四个细节
① 迭代器已经指向了最后一个元素的后一个位置,此时你还再次调用 next()
去获取元素的话,那么它会报 NoSuchElementException(没有这个元素异常)
② 迭代器遍历完成,指针是不会复位的
如果你还想将这个集合再次遍历一遍,需要重新再去获取一个迭代器的对象
第二次获取的时候,拿到的就是一个新的迭代器对象。
③ 循环中只能用一次 next()
,如果你想多次使用到当前遍历的元素,就只能先用一个变量去记录,在下面直接使用变量就行了。
④ 迭代器遍历的时候,不能用集合的方法进行增加或者删除。