迭代器
前两天学习了数据结构与算法中的有关线性表的内容,在自己写代码实现各种表的时候,都会用到迭代器对表进行遍历,之前并没有过多了解迭代器,借此机会好好学习一下。
迭代器常用与集合遍历,集合遍历包括三种,分别是迭代器遍历、增强for遍历以及lambda表达式遍历。不禁要想,之前我们遍历最常用的就是for循环,为什么这里没有了呢,是因为索引问题。我们之前遍历数组,数组是可以通过索引查找元素的,所以用不同的for循环就行。但是在集合Collection中,List集合有索引,但Set集合没有索引,因此就不能用for循环了,就有了上述三种遍历方法。
先来学习迭代器遍历。迭代器无非也是从头开始遍历集合,查找元素,不过迭代器不依赖索引,这是其特点。迭代器是一个对象(Iterator),我们是用它之前就要创建迭代器对象,可以简单的将其理解为是一个指针,指向集合的第一个元素(就可以按照数组,理解为索引0)。
Iterator<E> iterator()//返回一个迭代器对象
创建好一个Iterator后,指针会指向0索引,然后要判断这个位置是否有元素,有专门的判断方法。有返回true,没有返回false。
boolean hasNext()
之后就可以获取当前指针指向的元素,那想获取下一个元素的话我们是不是应该将指针往后移一位呀,这里又会用到一个方法,同时帮助我们实现这两个功能。
E next()
那我们该如何获取这个集合中的每一个元素呢?将while()循环和迭代器结合,就可以获取到集合中的每一个元素.
Iterator<String> it = list.iterator(); while(it.hasNext()){ String str = it.next(); System.out.println(str); }
迭代器细节注意点:
1.当指针已经指向空了,也就是到末尾的后面了,此时你要是非要继续获取元素,运行会报错,报NoSuchElementException,就是说已经没有元素给你取了。像我们遍历数组,索引查出了范围,会报索引越界的错误,但是集合没有索引,因此就报的没有数据的错误。
2.迭代完毕后,指针不会复位,要想重新迭代你就得再创建个迭代器对象
3.循环中只能用一次.next()方法。这个是为什么呢?看下面这段代码就知道了,collection中要是有偶数个元素是没问题的,要是奇数个元素就出错了,比如现在指针已经指向了eee,while判断后进入循环,第一个next()拿到了eee,那此刻指针是不是已经出去到,到了集合的范围外,那你在使用next()获取元素就肯定错了呀。
public static void main(String[] args) { //1.创建集合并添加元素 Collection<String > collection = new ArrayList<>(); collection.add("aaa"); collection.add("bbb"); collection.add("ccc"); collection.add("ddd"); collection.add("eee"); Iterator<String> iterator = collection.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next());//aaa ccc eee System.out.println(iterator.next());//bbb ddd null } }
4.在循环中,不能使用集合的方法进行增加或者删除。你要是不听劝用了,运行会报错ConcurrentModificationException,并发修改异常。如果想删除,可以用Iterator提供的remove()方法。
下面来看看在集合中,迭代器的原码是怎么实现的,我是在ArrrayList中找的。
发现有一个方法iterator(),它的返回值是一个Iterator的接口,因此要return一个Iterator对象。在ArrayList中,sun公司定义类一个内部类,我们知道内部类依然可以做接口实现和类的继承,这个内部类叫做Itr,实现了Iterator接口。
public Iterator<E> iterator() { //返回接口实现类的对象 return new Itr(); } /** * An optimized version of AbstractList.Itr */ //内部类 //无法直接访问这个内部类,因为已经私有了,只能通过iterator()这个方法获得内部类的对象。 private class Itr implements Iterator<E> { //要重写方法 public boolean hasNext(){ return false; } public Object next(){ return null; } public void remove(){ } }
那现在我们再来看一下 Iterator<String> iterator = collection.iterator();这句代码。collection.iterator()这里我们得到了一个对象,是哪个对象,是不是内部类对象,也就是Iterator这个接口实现类的对象,所以这个对象能调用接口中的方法,只不过是实现类中重写后的方法。
以上就是Iterator的基本内容,下面我将写写有关增强for遍历的内容。
增强for的底层就是迭代器,为了简化迭代器而书写的。
集合可以根据其存储结构分成两大类,分别是单列集合java.lang.Collection和双列集合java.lang.Map,只有的单列集合和数组才能用增强for遍历。
for(元素的数据类型 变量名:数组或集合){ } for(String s : list){ System.out.println(s);//s为第三方变量 }
增强for中的一个小细节,其中s仅仅是一个第三方变量而已,修改s不会改变原来的数据。不过是遍历集合的时候将元素用第三方变量记录而已。
又会了很多东西呀,一点点积累好兄弟们。
#如何看待2023届秋招##你的秋招进展怎么样了##0offer是寒冬太冷还是我太菜##我的求职思考#我是一个转码的小白,平时会在牛客中做选择题,在做题中遇到不会的内容就会去找视频或者文章学习,以此不断积累知识。这个专栏主要是记录一些我通过做题所学到的基础知识,希望能对大家有帮助