五(一)java高级-集合-集合与迭代器(二)

5.1.2 Iterator迭代器
1、Iterator
  • 所谓迭代器:就是用于挨个访问集合元素的工具/对象

方法:

  1. boolean hasNext():判断当前遍历集合后面是否还有元素可以迭代
  2. Object next():取出当前元素,并往后移→noSuchelementException
  3. void remove():删除刚刚迭代的对象
while(iterator.hasNext()){
	String s = (String) iterator.next();
    if(s.contain("a))
        iterator.remove();
}

Collection集合:Iterator iterator()方法

  • 返回当前遍历集合对象的一个迭代器对象,Iterator是一个接口,即返回Iterator接口的一个实现类对象,具体是哪个实现类对象,需要看集合类型。eg:Arrayist集合→返回ArrayList类中的Itr内部类,实现Iterator接口。
ArrayList arr = new ArrayList();
Iterator iterator = arr.iterator();
while(iterator.hasNext){
    System.out.println(iterator.next());
}
2、Iterator与Iterable

【java.lang.Iterable接口】:

  • 实现Iterable接口允许对象使用”foreach“语句进行遍历,其中数组和集合类都默认实现了Iterable接口(1.5增加)。
  • 内含的抽象方法:Iterator iterator():即实现Iterable接口本质上就是实现Iterator接口,Iterable需要依赖于Iterator。

【java.util.Iterator接口】

image-20240211150426543

3、Iterator原理
  • 删除集合元素:iterator.remove()、Collection里的removeIf()、remove(o)
//jdk1.8以后removeIf()
coll.removeIf(new Predicate(){
    @Override
    public bollean test(Object o) {
        return (String(o)).contains("o");
    }
});
  • coll.remove(s):并发修改异常ConcurrentModifacationException
//2、Iterator迭代时remove()方法:
Collection coll = new ArrayList();
coll.add("hihi");
coll.add("hello");
coll.add("world");
coll.add("zhang");
coll.add("san");

Iterator iterator = coll.iterator();
while (iterator.hasNext()){
    String s = (String) iterator.next();
    if(s.contains("o")){
        iterator.remove();
        //coll.remove(s);//.ConcurrentModificationException
    }
}
System.out.println(coll);
  • 出现漏删情况
//在foreach循环时删除
for (Object o : coll) {
    if(((String) o).contains("a")){
        coll.remove(o);//ConcurrentModificationException
    }
}
System.out.println(coll);

image-20240211143723226

【Iterator原理】

Iterator对象迭代元素的过程:

  1. 调用Iterator的next()之前,迭代器指向第一个元素,当第一次调用迭代器的next方法时,返回第一个元素,迭代器的索引向后移动一位,指向第二个元素;
  2. 再次调用next方法,返回第二个元素,迭代器的索引再向后移动一位,指向第三个元素;
  3. 依此类推,直到hasNext方法返回false,即全部迭代完成,结束对元素的遍历。

image-20240211150641264

【ArrayList里面源码分析】:

public Iterator<E> iterator() {
        return new Itr();
    }

创建了一个Iterator迭代器对象,返回ArrayList类中的Itr内部类,Itr内部类实现了Iterator接口。

image-20240211181355628
  • modCount:用于记录集合结构被修改的次数。
  • 对集合进行增添、删除→modCount++
  • 在用Iterator迭代器遍历集合时,创建集合迭代器的对象,会使用变量exceptionModCount记录当前集合的modCount。当进入next()方法时,会先判断exceptionModCount != modCount,如果不等于(集合结构发生了改变,modCount++)将抛出ConcurrentModificationException异常;如果相等则进行下一次迭代
private class Itr implements Iterator<E> {
    int cursor;       // 游标,指定当前集合索引
    int lastRet = -1; // 返回上一次遍历元素的索引,如果不存在为-1
    int expectedModCount = modCount;//迭代器创建时的modCount值
    
    Itr() {}

在ArrayList里,发现modCount变量定义在ArrayList的父类AbstractList里。在涉及add新增、remove删除、fastRemove、clear等会改变集合结构的操作,都会通过modCount++形式,增加列表在结构上被修改的次数。

//AbstractList.java
protected transient int modCount = 0;

modCount是这个list被结构性修改的次数。子类使用这个字段是可选的,如果子类希望提供fail-fast迭代器,它仅仅需要在add(int, E),remove(int)方法(或者它重写的其他任何会结构性修改这个列表的方法)中添加这个字段。调用一次add(int,E)或者remove(int)方法时必须且仅仅给这个字段加1,否则迭代器会抛出伪装的ConcurrentModificationExceptions错误。如果一个实现类不希望提供fail-fast迭代器,则可以忽略这个字。

public boolean hasNext() {
    return cursor != size;
}
  • 如果当前索引不等于集合大小,说明还有元素没有遍历完,返回ture将进行下一次迭代。
public E next() {
    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];
}
  • 检查exceptionModCount != modCount;如果相等,进入下一次迭代,不等,抛出异常。
final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

康康remove(o)

public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}
private void fastRemove(int index) {
    modCount++;
    ......
    }

image-20240211175736190

image-20240211181038290

【总结】:Iterator如何实现fail-fast机制的?

fail-fast产生的原因:在于程序在遍历过程中,某个线程对该 collection 在结构上对其做了修改,此时迭代器抛出 ConcurrentModificationException 异常信息,导致遍历失败,从而产生 fail-fast。由此可以看出fail-fast不允许在遍历的过程中对容器中的数据进行修改。

但是该异常不会始终指出对象已经由不同线程并发修改,如果单线程违反了规则,同样也有可能会抛出改异常。不能保证一定会出现该错误,但是快速失败操作会尽最大努力抛出ConcurrentModificationException异常,所以因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/383974.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

阿里云带宽计费模式怎么选?如何收费的?

阿里云服务器带宽计费模式分为“按固定带宽”和“按使用流量”&#xff0c;有什么区别&#xff1f;按固定带宽是指直接购买多少M带宽&#xff0c;比如1M、5M、10M、100M等&#xff0c;阿里云直接分配用户所购买的带宽值&#xff0c;根据带宽大小先付费再使用&#xff1b;按使用…

锐捷(二十一)全局地址绑定

vlan划分和vlanif接口配置略&#xff0c;注意vlanif接口里要no shutdown配置如下&#xff1a; Address-bind 192.168.1.1 AAAA.BBBB.CCCCAddress-bind uplink g0/0Address-bind binding-filter loggingAddress-bind install 此时&#xff0c;IP为192.168.1.1 mac地址为AAAA.B…

Win10截图的四种方式

截图不一定要依靠通讯软件&#xff0c;现在系统自己就带有这些功能。 1.Win Shift S组合键&#xff1a;选择微信截图&#xff0c;部分截图&#xff0c;随心所欲&#xff1b; 2.Win W组合键&#xff1a;呼出屏幕右侧的工作区&#xff0c;选择屏幕草图&#xff0c;支持裁剪、编辑…

《SQLi-Labs》05. Less 29~37

title: 《SQLi-Labs》05. Less 29~37 date: 2024-01-17 22:49:10 updated: 2024-02-12 18:09:10 categories: WriteUp&#xff1a;Security-Lab excerpt: HTTP 参数污染&#xff0c;联合注入、宽字节注入。 comments: false tags: top_image: /images/backimg/SunsetClimbing.p…

【深度学习】基于多层感知机的手写数字识别

案例2&#xff1a;构建自己的多层感知机: MNIST手写数字识别 相关知识点: numpy科学计算包&#xff0c;如向量化操作&#xff0c;广播机制等 1 任务目标 1.1 数据集简介 ​ MNIST手写数字识别数据集是图像分类领域最常用的数据集之一&#xff0c;它包含60,000张训练图片&am…

【C语言】实现单链表

目录 &#xff08;一&#xff09;头文件 &#xff08;二&#xff09;功能实现 &#xff08;1&#xff09;打印单链表 &#xff08;2&#xff09;头插与头删 &#xff08;3&#xff09;尾插与尾删 &#xff08;4&#xff09; 删除指定位置节点 和 删除指定位置之后的节点 …

DevOps:CI、CD、CB、CT、CD

目录 一、软件开发流程演化快速回顾 &#xff08;一&#xff09;瀑布模型 &#xff08;二&#xff09;原型模型 &#xff08;三&#xff09;螺旋模型 &#xff08;四&#xff09;增量模型 &#xff08;五&#xff09;敏捷开发 &#xff08;六&#xff09;DevOps 二、走…

SpringCloud-高级篇(二十)

下面我们研究MQ的延迟性问题 &#xff08;1&#xff09;初始死信交换机 死信交换机作用一方面可以向Public的异常交换机一样做异常消息的兜底方案&#xff0c;另一方面&#xff0c;可以处理一些超时消息&#xff0c;功能比较丰富一点 &#xff08;2&#xff09;TTL 上面学习…

Python:函数和lambda表达式

函数实质性特定任务的一段代码&#xff0c;程序通过将一段代码定义成函数&#xff0c;并为该函数指定一个函数名&#xff0c;这样即可在需要的时候多次调用这段代码。因此&#xff0c;函数是代码复用的重要手段。 与函数紧密相关的一个知识点就是lambda表达式。lambda表达式可…

【C语言】C的整理记录

前言 该笔记是建立在已经系统学习过C语言的基础上&#xff0c;笔者对C语言的知识和注意事项进行整理记录&#xff0c;便于后期查阅&#xff0c;反复琢磨。C语言是一种面向过程的编程语言。 原想在此阐述一下C语言的作用&#xff0c;然而发觉这些是编程语言所共通的作用&#…

controller-manager学习三部曲之二:源码学习

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 作为《controller-manager学习三部曲》系列的第二篇&#xff0c;前面通过shell脚本找到了程序的入口&#xff0c;接下来咱们来学习controller-mana…

数据库管理-第149期 Oracle Vector DB AI-01(20240210)

数据库管理149期 2024-02-10 数据库管理-第149期 Oracle Vector DB & AI-01&#xff08;20240210&#xff09;1 机器学习2 向量3 向量嵌入4 向量检索5 向量数据库5 专用向量数据库的问题总结 数据库管理-第149期 Oracle Vector DB & AI-01&#xff08;20240210&#xf…

【JVM篇】ThreadLocal中为什么要使用弱引用

文章目录 &#x1f354;ThreadLocal中为什么要使用弱引用⭐总结 &#x1f354;ThreadLocal中为什么要使用弱引用 ThreadLocal可以在线程中存放线程的本地变量&#xff0c;保证数据的线程安全 ThreadLocal是这样子保存对象的&#xff1a; 在每个线程中&#xff0c;存放了一个…

以谷歌浏览器为例 讲述 JavaScript 断点调试操作用法

今天来说个比较实用的东西 用浏览器开发者工具 对 javaScript代码进行调试 我们先创建一个index.html 编写代码如下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content&…

【每日一题】牛客网——链表分割

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有…

使用R语言fifer包进行分层采样

使用R语言fifer包中的stratified()函数用来进行分层采样非常方便&#xff0c;但fifer包已经从CRAN存储库中删除&#xff0c;需要从存档中下载可用的历史版本&#xff0c;下载链接&#xff1a;Index of /src/contrib/Archive/fifer (r-project.org)https://cran.r-project.org/s…

C# WinForm开发系列 - DataGridView

原文地址&#xff1a;https://www.cnblogs.com/peterzb/archive/2009/05/29/1491891.html 1.DataGridView实现课程表 testcontrol.rar 2.DataGridView二维表头及单元格合并 DataGridView单元格合并和二维表头.rar myMultiColHeaderDgv.rar 3.DataGridView单元格显示GIF图片 …

数据结构~~树(2024/2/8)

目录 树 1、定义&#xff1a; 2、树的基本术语&#xff1a; 3、树的表示 树 1、定义&#xff1a; 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&…

大数据Doris(六十五):基于Apache Doris的数据中台2.0

文章目录 基于Apache Doris的数据中台2.0 一、​​​​​​​架构升级

数据库基础学习笔记

一.基础概念 数据库、数据库管理系统、SQL 主流数据库&#xff1a; mysql的安装&#xff1a;略 mysql图形化界面的安装&#xff1a;略 二.数据模型 1). 关系型数据库&#xff08;RDBMS&#xff09; 概念&#xff1a;建立在关系模型基础上&#xff0c;由多张相互连接的二维表…