关于使用迭代器对集合进行遍历时,不能对集合进行修改的论证## 标题 ##

摘要:迭代器再帮助我们进行对集合的元素进行遍历提供了有效的方法,java采用迭代器模式能在不暴露集合对象内部元素的情况下,对元素进行访问。

1.使用迭代器的优点

Collection中的remove()方法需要先查找到需要删除元素的位置,这本身就需要一定的开销

如果在使用迭代器进行对集合的遍历时,对集合自身产生结构上的变化的时候(add.remove,clear等),例如:遍历时对集合当前向的下一项做了删除的操作,当再一次调用next(),就会出现混乱,下文会从源码的角度对其进行分析。

2.接口Iterator源码

public interface Iterator{

//获取下一个元素,第一次调用给出第一项,第二次给出第二项,。。。

E next();

//是否存在下一个,存在true,不存在false

boolean hasNext();

//从底层集合中删除迭代器返回的最后一个元素,就是next()返回的集合中的元素

default void remove() {

throw new UnsupportedOperationException("remove");

}

//对每个剩余的元素进行一定的操作

default void forEachRemaining(Consumer super E> action) {

Objects.requireNonNull(action);

while (hasNext())

action.accept(next());

}

}

3.测试实例

@Test

public void test_Iterator() {

List list = new ArrayList<>();

list.add("唐三藏");

list.add("孙悟空");

list.add("猪八戒");

list.add("沙和尚");

list.add("白龙马");

for(Iterator iter = list.iterator();iter.hasNext();{

if("猪八戒".equals(iter.next())) {

list.add("高小姐");

}

}

}

测试结果:java.util.ConcurrentModificationException

4.源码解读

private class Itr implements Iterator{//Itr类作为ArrayList的内部类

int cursor; // 下一个元素的索引

int lastRet = -1; // 最后一个元素索引

int expectedModCount = modCount;//预期集合元素数量

public boolean hasNext() {

//size外部类集合的大小

return cursor != size;

}

@SuppressWarnings("unchecked")

public E next() {

//关键一步,调用checkForComodification()会去校验expectedModCount 和modCount是否相等,不等抛异常

//modCount 字段作为外部类结构修改次数的记录,为子类提供快速迭代,上文实例抛错就是出自此处

checkForComodification();

int i = cursor;

if (i >= size)

throw new NoSuchElementException();

Object[] elementData = ArrayList.this.elementData;

if (i >= elementData.length)

throw new ConcurrentModificationException();

cursor = i + 1;

return (E) elementData[lastRet = i];

}

public void remove() {

if (lastRet < 0)

throw new IllegalStateException();

checkForComodification();

try {

ArrayList.this.remove(lastRet);

cursor = lastRet;

lastRet = -1;

expectedModCount = modCount;

} catch (IndexOutOfBoundsException ex) {

throw new ConcurrentModificationException();

}

}

@Override

@SuppressWarnings("unchecked")

public void forEachRemaining(Consumer super E> consumer) {

Objects.requireNonNull(consumer);

final int size = ArrayList.this.size;

int i = cursor;

if (i >= size) {

return;

}

final Object[] elementData = ArrayList.this.elementData;

if (i >= elementData.length) {

throw new ConcurrentModificationException();

}

while (i != size && modCount == expectedModCount) {

consumer.accept((E) elementData[i++]);

}

// update once at end of iteration to reduce heap write traffic

cursor = i;

lastRet = i - 1;

checkForComodification();

}

final void checkForComodification() {

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

}

}

源码解读:对集合进行迭代器遍历的时候,调用hashNext(),查看下一个元素的索引是否和集合的大小相等,相等表示已经到了集合的末尾,不存在下一个元素返回false;调用next()方法会先调用checkForComodification()方法来确保对集合修改次数一致,不一致抛异常,如果此时我们调用集合的remove(int index),就会去修改modCount 字段的次数,等下次再调用迭代器的next()方法的时候,值就会不一致 ,出现异常。同时,从逻辑的角度上来说,当我们对集合进行迭代的时候,如果对集合进行结构上的修改,直接会影响迭代器的遍历,产生不可预知的结果,所以在迭代器进行遍历的时候集合是不能对集合自身进行修改的。

java迭代器不能修改集合值_关于使用迭代器对集合进行遍历时,不能对集合进行修改的论证...相关推荐

  1. java函数返回多个值_深入理解被调函数与主调函数之间的传值、传址、值返回、址返回...

    函数的英文是function,有功能的意思,函数的作用在于合理分配功能,增强程序的可读性.合理分解功能,降低程序的复杂性.隐藏函数内部的数据和实现,尽可能将问题局限于函数本身. 函数可以理解为一种功能 ...

  2. python集合运算_从零开始学Python - 第014课:常用数据结构之集合

    在学习了列表和元组之后,我们再来学习一种容器型的数据类型,它的名字叫集合(set).说到集合这个词大家一定不会陌生,在数学课本上就有这个概念.通常我们对集合的定义是"把一定范围的.确定的.可 ...

  3. r语言集合补集_【高中数学必修1研读】之一“第一章 集合与函数概念”

    第一章:集合与函数概念 [导入例子] "神舟"五号载人航天飞船离地面的距离随时间的变化而变化:上网费用随着上网时间的变化而变化:出国旅游人数日益增多:城市绿化面积不断扩大..... ...

  4. struts 修改拦截器修改返回值_关于struts2简单的介绍与示例

    Apache Struts 2是一个用于开发Java EE网络应用程序的开放源代码网页应用程序架构.它利用并延伸了Java Servlet API,鼓励开发者采用MVC架构. 缘起于Apache St ...

  5. java获取注解的属性值_反射+自定义注解,实现获取注解标记的属性

    目标:通过自定义注解 @Ignore 注解,觉得是否读取指定类的属性. 运行结果: [main] INFO util.FruitInfoUtil -水果的名字为:entity.Apple [main] ...

  6. java冒泡排序找最大的值_(13)數組操作:遍歷、輸出最大值、冒泡排序、選擇排序,java已有的排序方法、折半查找...

    1.數組遍歷 /* * 獲取數組中元素,遍歷 */ int []y=new y[3]; for(int i=0;i { System.out.println("y["+i+&quo ...

  7. std::list 修改某个值_在WordPress首页不显示某个分类文章的做法

    WordPress作为博客站点很好用,但可惜的是没有微博/twitter之类快速短文的功能,如果设置一个分类来放置这类短文,首页又会显得杂乱而没有章法,按照网络上的教程,这个问题有几种解决办法,自己采 ...

  8. java 怎么获取键的值_在 Java 中如何获取 Map 的所有键和值

    在 Java 中可以通过 map.entrySet() 方法获取 Map 的所有键和值. Map map = new HashMap<>(); // Get keys and values ...

  9. java逆波兰式求值_波兰式、逆波兰式与表达式求值

    波兰式.逆波兰式是<数据结构>课程中讲解关于栈的时候提到的,栈是很简单的一种数据结构.但是这些理论的提出却是计算机早期发展领域的重大突破,值得仔细回味. 1. 中缀表达式 我们在数学中学到 ...

最新文章

  1. android 九宫格绘制,Android draw9patch.bat 九宫格绘制工具使用
  2. 携手百度 英特尔三大领域布局人工智能市场
  3. view函数_数据科学系列:数据处理(6)字符串函数基于R(二)
  4. Oracle查询优化-01单表查询
  5. MongoDB练习题
  6. TSC条码打印机亮红灯解决办法!
  7. python 矩阵元素平方_NumPy之计算两个矩阵的成对平方欧氏距离
  8. Java全栈开发---Java ERP系统开发:商业ERP(十二)数据的导入导出(Excel)
  9. xshell linux 打开多个窗口快捷键,linux,xshell,快捷键
  10. java实现图片上传后裁剪,把白色背景变成透明图(电子印章)
  11. Python 创建子线程
  12. r语言使用linux命令,技术|如何在 Ubuntu 上安装和使用 R 语言
  13. Fortran语法汇总(上)
  14. revit二次开发 材质相关
  15. Microbit蓝芽配对
  16. 【CMU15-445数据库】bustub Project #0:Trie 树实现(C++ Primer)
  17. 如何让点聚WebOffice在线编辑ActiveX插件兼容火狐、谷歌、IE各式浏览器
  18. [质数筛] 质数筛算法详解
  19. linux 调整屏幕亮度、待机、休眠命令
  20. docker runc 版本升级

热门文章

  1. 数据结构(C++)—— 向量(Vector)
  2. C++ 类中特殊成员变量(常量、静态、引用)的初始化方法
  3. csrf token invalid什么意思_Spring Cloud Gateway 实现Token校验
  4. 没有计算机基础可以学python-零基础,没有编程和计算机基础,究竟该怎么自学python?...
  5. python学习网站-关于python学习,最系统的学习网站看这里
  6. python代码实例-python程序实例
  7. python和c语言的区别-c语言和python的区别是什么
  8. 如何系统的自学python-如何系统地自学Python
  9. python怎么读写文件-python3 excle(python怎么读写excel文件)
  10. python自动化办公真的好用吗-python如何实现自动化办公?