一、迭代器概述

  1、什么是迭代器?

  在Java中,有很多的数据容器,对于这些的操作有很多的共性。Java采用了迭代器来为各种容器提供了公共的操作接口。这样使得对容器的遍历操作与其具体的底层实现相隔离,达到解耦的效果。

  在Iterator接口中定义了三个方法:

  

  2、迭代器使用

  1. public static void main(String[] args)
  2. {
  3. List<String> list=new ArrayList<>();
  4. list.add("abc");
  5. list.add("edf");
  6. list.add("ghi");
  7. for(Iterator<String> it=list.iterator();it.hasNext();)
  8. {
  9. System.out.println(it.next());
  10. }
  11. }

 执行结果: 

二、ArrayList的Iterator实现

  1.    private class Itr implements Iterator<E>
      {
  2. int cursor; // index of next element to return
  3. int lastRet = -1; // index of last element returned; -1 if no such
  4. int expectedModCount = modCount;
  5. ...
  6. }

  在ArrayList内部定义了一个内部类Itr,该类实现了Iterator接口。

  在Itr中,有三个变量分别是

  cursor:表示下一个元素的索引位置

  lastRet:表示上一个元素的索引位置

  expectModCount:预期被修改的次数

  下面看一下Itr类实现了Iterator接口的三个方法:

  1. public boolean hasNext()
  2. {
  3. return cursor != size;//当cursor不等于size时,表示仍有索引元素
  4. }
  1. public E next() //返回下一个元素
  2. {
  3. checkForComodification();
  4. int i = cursor;
  5. if (i >= size)
  6. throw new NoSuchElementException();
  7. Object[] elementData = ArrayList.this.elementData;
  8. if (i >= elementData.length)
  9. throw new ConcurrentModificationException();
  10. cursor = i + 1;
  11. return (E) elementData[lastRet = i];
  12. }

  在next()方法中有一个checkForComodification()方法,其实现为:

  1. final void checkForComodification()
  2. {
  3. if (modCount != expectedModCount)
  4. throw new ConcurrentModificationException();
  5. }

  可以看到,该函数是用来判断集合的修改次数是否合法。

  在集合内部维护一个字段modCount用于记录集合被修改的次数,每当集合内部结构发生变化(add,remove,set)时,modCount+1。

  在迭代器内部也维护一个字段expectedModCount,同样记录当前集合修改的次数,初始化为集合的modCount值。当我们在调用Iterator进行遍历操作时,如果有其他线程修改list会出现modCount!=expectedModCount的情况,就会报并发修改异常java.util.ConcurrentModificationException。下面为示例代码:

  1. public static void main(String[] args)
  2. {
  3. ArrayList<String> aList=new ArrayList<String>();
  4. aList.add("bbc");
  5. aList.add("abc");
  6. aList.add("ysc");
  7. aList.add("saa");
  8. System.out.println("移除前:"+aList);
  9.  
  10. Iterator<String> it=aList.iterator();
  11. while(it.hasNext())
  12. {
  13. if("abc".equals(it.next()))
  14. {
  15. aList.remove("abc");
  16. }
  17. }
  18. System.out.println("移除后:"+aList);
  19. }

  

  上面的代码中,如果我们只使用迭代器来进行删除,则不会出现并发修改异常错误。

  1.   public static void main(String[] args)
  2. {
  3.     ArrayList<String> aList=new ArrayList<String>();
  4. aList.add("bbc");
  5. aList.add("abc");
  6. aList.add("ysc");
  7. aList.add("saa");
  8. System.out.println("移除前:"+aList);
  9.  
  10. Iterator<String> it=aList.iterator();
  11. while(it.hasNext())
  12. {
  13. if("abc".equals(it.next()))
  14. {
  15. it.remove();
  16. }
  17. }
  18. System.out.println("移除后:"+aList);
  19. }

  

  1. public void remove()
  2. {
  3. if (lastRet < 0)
  4. throw new IllegalStateException();
  5. checkForComodification();
  6. try {
  7. ArrayList.this.remove(lastRet);
  8. cursor = lastRet;
  9. lastRet = -1;
  10. expectedModCount = modCount;
  11. } catch (IndexOutOfBoundsException ex) {
  12. throw new ConcurrentModificationException();
  13. }
  14. }

  在执行remove操作时,同样先执行checkForComodification(),然后会执行ArrayList的remove()方法,该方法会将modCount值加1,这里我们将expectedModCount=modCount,使之保持统一。

三、ListIterator

  上面可以看到,Iterator只提供了删除元素的方法remove,如果我们想要在遍历的时候添加元素怎么办?

  ListIterator接口继承了Iterator接口,它允许程序员按照任一方向遍历列表,迭代期间修改列表,并获得迭代器在列表中的当前位置。

  ListIterator接口定义了下面几个方法:

  

  下面使用ListIterator来对list进行边遍历边添加元素操作:

  1. public static void main(String[] args)
  2. {
  3. ArrayList<String> aList = new ArrayList<String>();
  4. aList.add("bbc");
  5. aList.add("abc");
  6. aList.add("ysc");
  7. aList.add("saa");
  8. System.out.println("移除前:" + aList);
  9. ListIterator<String> listIt = aList.listIterator();
  10. while (listIt.hasNext())
  11. {
  12. if ("abc".equals(listIt.next()))
  13. {
  14. listIt.add("haha");
  15. }
  16. }
  17. System.out.println("移除后:" + aList);
  18. }

  

   

    

Java集合Iterator迭代器的实现的更多相关文章

  1. Java集合中迭代器的常用用法

    该例子展示了一个Java集合中迭代器的常用用法public class LinkedListTest { public static void main(String[] args) { List&l ...

  2. JAVA基础——集合Iterator迭代器的实现

    一.迭代器概述 1.什么是迭代器? 在Java中,有很多的数据容器,对于这些的操作有很多的共性.Java采用了迭代器来为各种容器提供了公共的操作接口.这样使得对容器的遍历操作与其具体的底层实现相隔离, ...

  3. Java 集合:迭代器(Iterator, Iterable)

    Iterator接口 public interface Iterator<E> { boolean hasNext(); E next(); void remove(); } 访问元素前需 ...

  4. java集合-Iterator迭代

    我们常常使用 JDK 提供的迭代接口进行 Java 集合的迭代. Iterator iterator = list.iterator(); while(iterator.hasNext()){ Str ...

  5. Java之iterator迭代器和iterable接口

    java.lang.Iterable java.util.Iterator Iterator是迭代器类,而Iterable是接口. 好多类都实现了Iterable接口,这样对象就可以调用iterato ...

  6. Java集合--Iterator和Enumeration比较

    转载请注明出处:http://www.cnblogs.com/skywang12345/admin/EditPosts.aspx?postid=3311275 第1部分 Iterator和Enumer ...

  7. JAVA集合--Iterator接口

        本文首发于cartoon的博客     转载请注明出处:https://cartoonyu.github.io/cartoon-blog     上一篇文章中我在集合元素的遍历中已经有涉及到I ...

  8. 集合——iterator迭代器

    Iterator接口: Iterator接口使用: 其中,集合Collection接口的定义也是使用多态,必须要创建它的子类对象才行,子类接口也是不能直接创建对象的(List接口): 其中wihle的 ...

  9. 【Java】Iterator迭代器总结

    迭代器是一个对象,它的工作时遍历并选择序列中的对象,而客户端程序员不必知道或关心该序列底层的结构,此外,迭代器通常被称为轻量级对象:创建它的代价小.因此,经常可以见到对迭代器有些奇怪的限制,例如Jav ...

随机推荐

  1. BW基于ALE的主数据增量机制分析

    1     概述 前段时间在项目中碰到一个问题,地点物料0MAT_PLANT_ATTR属性主数据因为有两个多月没有做增量更新,导致在之后的每次增量抽取活动中因为抽取的数据量过大使得在源系统的进程中发生 ...

  2. 如何修改 EM12c 中 SYSMAN 用户的密码?

    以下内容全部转自:http://www.chenjunlu.com/2013/04/how-to-modify-the-password-for-sysman-of-em-12c-cloud-cont ...

  3. 关于在mac 配置eclipse c开发

    新建一个c 项目,如下 勾选hello world ANSL project ,勾选右边的MacOSX GCC 安装插件CDT - http://download.eclipse.org/tools/ ...

  4. SAP顾问发展

    关于SAP顾问发展的话题也不仅仅是一次的谈起,但是我想对于自己的规划很多人是否有没有深刻的考虑过.这对于你我来说都非常的重要,那么作为我来说,我仅仅把自己的观点阐述以供大家思考,希望对大家能有所帮助. ...

  5. 初探Stage3D(二) 了解AGAL

    关于本文 本文并无打算事无巨细的介绍一遍AGAL,仅仅是对现有文档的一些理解及汇总,所以请先阅读相参考文档 AGAL概念 参考资料 http://www.adobe.com/devnet/flashp ...

  6. elasticsearch + hive环境搭建

    一.环境介绍: elasticsearch:2.3.1 hive:0.12 二.环境搭建 2.1 首先获取elasticsearc-hadoop的jar包 链接地址:http://jcenter.bi ...

  7. IPv4分析

    IPv4的头部格式: 1. Version 版本号,默认是4. 2. IHL(Internet Header Length) 就是IPv4头部长度.这个长度的单位是32bit,一般是5,那么头部的长度 ...

  8. QWidget::paintEngine: Should no longer be called

    Qt新手,其实并不知道出现这个问题的本质原因,我的问题在于paintEvent中使用的painter是类的成员而不是临时新建的局部变量,改为使用局部变量问题就消失了.

  9. 搭建WebRtc环境

    0.前言 这次的需求,准备做的是一个类似与QQ视频一样的点对点视频聊天.这几天了解了一些知识后,决定使用HTML5新支持的WebRtc来作为视频通讯.客户端使用支持HTML5浏览器即可.服务器段需要提 ...

  10. [转载]AxureRP 7超强部件库下载

    很多刚刚开始学习Axure的朋友都喜欢到网上搜罗各种部件库(组件库)widgets library ,但是网络中真正实用的并且适合你使用的少之又少,最好的办法就是自己制作适合自己工作内容的部件库. 这 ...