Java迭代器与Collection接口超详细讲解
作者:扎哇太枣糕
关于迭代器你都知道什么?
什么是迭代器?
所谓迭代的意思就是交换替代,迭代器并不是一种数据结构或者集合,而是可以过迭代器中的方法逐个访问集合中的每个元素的一种方法。提到迭代器最重要的就是Iterator接口,所有想要使用迭代器迭代的结构都需要实现或者继承这个接口
迭代器的4个API
Iterator接口包含4个方法,分别是next、hasNext、remove、forEachRemaining,接下来在学习构造器如何使用之前我们先学习一下它的四种方法
首先一开始构造器中的有一个类似于指针的标志,指在集合中第一个元素的前面,调用构器中的next方法会使这个"指针"的位置后移到第一和二个元素之间,然后返回它跨过的那个元素给构造器,也就是第一个元素,如果"指针"到最后一个元素后面再调用next方法的话就会导致抛出NoSuchElementException
remove方法则是删除当前元素,可以理解为next方法返回的那个元素,如果调用remove方法之前没有调用next方法或者是使用remove方法删除该元素之后都会导致构造器为空,此时调用remove方法就会导致程序抛出IllegalStateExceptions异常
hasNext方法就是判断迭代器是否还有可迭代的下一个元素,如果有的话就返回true否则返回false,为了避免上述两种异常,remove方法每次都要配合另外两种方法一起使用,每次调用next方法之前都使用hasNext方法判断一下,避免没有可迭代元素导致的异常,每一次调用remove之前都使用next方法获得元素,避免迭代器为空导致的状态异常
forEachRemaining方法则可以直接遍历迭代器中的每一个元素并调用方法参数中的Lambda表达式,直到迭代器将集合的元素全部迭代完为止
如何使用迭代器?
接下来将结合上面的描述给出一个将集合中的元素全部删除的标准代码,然后再给出两个错误的代码,大家可以在使用迭代器的时候规避一下
正确写法
// 创建一个ArrayList集合 Collection<String> strings = new ArrayList<>(); strings.add("a"); strings.add("b"); strings.add("c"); strings.add("d"); // 获得迭代器对象 Iterator<String> iterator = strings.iterator(); // 使用while循环迭代集合中元素 使用hasNext方法判断 while (iterator.hasNext()) { // 使用next获取下一个元素 iterator.next(); // 删除这个元素 iterator.remove(); // 打印集合中元素 System.out.println(strings); }
错误示范一
// 创建一个ArrayList集合 Collection<String> strings = new ArrayList<>(); strings.add("a"); strings.add("b"); strings.add("c"); strings.add("d"); // 获得迭代器 Iterator<String> iterator = strings.iterator(); // 使用while循环迭代集合中元素 使用next方法判断下一个元素是否为空 while (iterator.next() != null) { // 输出这个元素 System.out.println(iterator.next()); }
第一个的错误原因:使用next方法判断下一个元素是否为空,这样就会导致"指针"到最后一个元素后面依旧会执行next方法,这样就会导致抛出NoSuchElementException异常;而且next方法每调用一次都会将"指针"向后移动一位,哪怕只是用于if判断。所以程序就会每隔一个元素输出一次,最后抛出NoSuchElementException异常
错误示范二
// 创建一个ArrayList集合 Collection<String> strings = new ArrayList<>(); strings.add("a"); strings.add("b"); strings.add("c"); strings.add("d"); // 获取迭代器对象 并使用while循环迭代集合中元素 使用hasNext方法判断 while (strings.iterator().hasNext()) { // 获取迭代器对象 并使用next获取下一个元素 然后输出 System.out.println(strings.iterator().next()); }
第二个的错误原因:每使用iterator方法获得一次集合对应的迭代器对象,都会默认将"指针"放到第一个元素的前面,于是第二个错误示范中一直使用集合中的第一个元素"a"进行判断有没有下一个元素,所以会导致程序陷入死循环,循环体里也会一直创建结合的迭代器对象,并将"指针"放到第一个元素的前面,然后调用next方法输出元素"a"
Collection集合接口知多少?
集合大体上可以分为两种,一种是单列的Collection集合,一种就是双列的Map集合,所谓的单双列可以理解为元素中数据的个数,单列集合一个数据作为元素存储,双列集合两个具有映射关系的数据作为元素存储。这一篇我们先学习Collection集合接口的内容,Collection集合按照元素存储是否有序又可分为List集合、Set集合
前面之所以先学习Iterator接口的原因就是,Collection接口继承了Iteator接口,于是它的子接口set和list都可以使用迭代器对集合中的元素进行迭代
为什么不使用数组而是集合?
在学习集合之前,我们将存储多个对象或者元素的任务都交给了数组,但是数组存储元素有以下缺点:
①数组一旦初始化之后,长度就确定不可修改,元素个数超出数组长度的话会抛异常。
②数组中提供的API很少,增加元素需要现将索引后的元素后移空出位置将元素添加进去,删除元素需要删除之后将后面的元素前移将空出来的位置补足,以上操作只能通过代码实现并没有现成的API可以使用。
③数组存储数据的特点:有序、可重复,对于一些无需、不可重复的业务需求就很难满足
集合就可以很好的弥补数组的上述缺点,而且集合提供了一组较为完善的数据结构,我们可以根据具体的业务需求来选择具体使用的集合类型。比如说存储元素无序不可重复的Set集合,有序可重复的List集合,具有映射关系的Map集合等
Collection接口的API都有什么?
AbstractCollection类知多少?
以上给出的Collection接口中的API都是抽象方法,也就意味着每一个此接口的实现类都需要重写这些抽象方法,实际上Collection接口的直接或者间接实现类有很多,如果每一个都需要重写这些方法的话就会很是麻烦。于是Java类库的设计者提供了AbstractCollection类,该类中只将size方法和Iterator方法声明为抽象,其他方法都提供了默认实现,如果子类不提供这些方法的方法体的话就使用该类中的默认实现
下图可知,list、set集合的实现类都直接或者间接的继承了AbstractCollection类,为的就是简化重写Collection接口的抽象方法
到此这篇关于Java迭代器与Collection接口超详细讲解的文章就介绍到这了,更多相关Java迭代器与Collection接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!