如何使用迭代器iterator循环删除容器中的元素?

Anaconda下安装LabelImg 阅读详情

STL中的容器主要分两类,一是顺序存储的,如vector;一是以红黑树形式存储的,如map。下面分别以vector和map为例,说明怎样利用迭代器在遍历的同时删除容器内元素。

下面示例程序首先往容器中添加一定元素,然后循环删除其中连续或不连续的元素。程序在VS2003以及g++3.4下调试,不同编译器下可能结果不同。
// vector sample for Windows and Linux
int main()
{
 vector<int> vec;
 vector<int>::iterator iter;
 vec.reserve(10);
 for ( int i = 0; i < 10; i++ )
 {
  vec.push_back( i );
 } 

 // delete the elements from 3 to 5 and 9.
 for ( iter = vec.begin(); iter != vec.end(); )
 {  
  cout << "Position " << *iter << ": ";

  if ( *iter == 3 )
  {
   vec.erase( iter ); cout << *iter;
  }
  else if ( *iter == 4 )
  {
   vec.erase( iter );  cout << *iter;     
  }
  else if ( *iter == 5 )
  {
   vec.erase( iter );  cout << *iter;
  }
  else if ( *iter == 9 )
  {
   vec.erase( iter );  cout << *iter;
  }
  else
  {
   cout << *iter;
   ++iter;
  }

  cout << endl;
 }       

 cout << "The left elements:" << endl;
 for ( iter = vec.begin(); iter != vec.end(); ++iter )
 {  
  cout << *iter << " ";
 }
 cout << endl;
   
 return 0;
}
如果上面程序中要在for循环中使用++iter的话,就需要在删除元素后做一次--iter操作,但这样的效率显然没有上面代码效率高。注意到vector的erase方法在执行后,当前迭代器自动指向了下一个元素位置,这也是为什么不要在删除元素后再++iter的原因。至于为啥当前迭代器会自动指向下一个位置呢,看gcc下vector的源码就知道了:
iterator erase(iterator position)
  {
    if (position + 1 != end())
      copy(position + 1, finish, position);  // 后续元素往前移动
    --finish;
    destroy(finish); // 一个释放资源的全局函数
    return position;
  }
从上面代码可以看出,vector中删除一个元素后,此位置以后的元素都需要往前移动一个位置,虽然当前迭代器位置没有自动加1,但是由于后续元素的顺次前移,也就相当于迭代器的自动指向下一个位置一样。

// map sample for Windows
int main()
{
 map<int,int> tree;
 map<int,int>::iterator iter; 
 for ( int i = 9; i > 0; i-- )
 {
  tree.insert(make_pair<int ,int>(i,i));
 } 

 // delete the elements from 3 to 5 and 9.
 for ( iter = tree.begin(); iter != tree.end(); )
 {  
  cout << "Position " << iter->first << ": ";

  if ( iter->first == 3 )
  {   
   iter = tree.erase( iter ); cout << iter->second;
  }
  else if ( iter->first == 4 )
  {
   iter = tree.erase( iter );  cout << iter->second;     
  }
  else if ( iter->first == 5 )
  {
   iter = tree.erase( iter );  cout << iter->second;
  }
  else if ( iter->first == 9 )
  {
   iter = tree.erase( iter );  cout << iter->second;
  }
  else
  {
   cout << iter->second;
   ++iter;
  }

  cout << endl;
 }       

 cout << "The left elements:" << endl;
 for ( iter = tree.begin(); iter != tree.end(); ++iter )
 {  
  cout << iter->first << " ";
 }
 cout << endl;
   
 return 0;
}
值得注意的是,由于map 的内部存储机制与vector不一样,所以map的erase方法执行后并没有把当前迭代器自动置为下一个元素位置,而是需要从erase的返回值获取下一个迭代器位置。当然vector的erase方法也同样可以返回下一个位置的指针。map的内部数据结构是红黑树,也就是二叉平衡树,使用erase删除一个元素后,树需要进行重新调整,因为不同于vector的顺序存储,所以map中erase方法中当前迭代器没有自动指向下一个节点位置,而是指向被删除的节点,而此节点已经被释放,如下面从gcc的红黑树实现中摘录的代码:
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
inline void
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(iterator position)
{
// 下面函数在从树中删除当前节点链接,并对树进行旋转,以维护平衡
  link_type y = (link_type) __rb_tree_rebalance_for_erase(position.node,
                                                          header->parent,
                                                          header->left,
                                                          header->right);
  destroy_node(y);  // 释放被删除节点
  --node_count;
}
从上述STL源码可以看出,由于Linux下STL库中map类的erase方法实现不一样, erase没有返回值,所以只能采用如下代码进行循环erase操作:
// map sample for Windows and Linux
int main()
{
 map<int,int> tree;  
 for ( int i = 9; i > 0; i-- )
 {
  tree.insert(make_pair<int ,int>(i,i));
 } 

 map<int,int>::iterator iter;
 // delete the elements from 3 to 5 and 9.
 for ( iter = tree.begin(); iter != tree.end(); ++iter )
 {  
  cout << "Position " << iter->first << ": ";

  if ( iter->first == 3 )
  {   
   tree.erase( iter-- );  cout << iter->second;
  }
  else if ( iter->first == 4 )
  {
   tree.erase( iter-- );  cout << iter->second;     
  }
  else if ( iter->first == 5 )
  {
   tree.erase( iter-- );  cout << iter->second;
  }
  else if ( iter->first == 9 )
  {
   tree.erase( iter-- );  cout << iter->second;
  }
  /*else
  {
   cout << iter->second;   
  }*/
  
  cout << endl;
 }       

 cout << "The left elements:" << endl;
 for ( iter = tree.begin(); iter != tree.end(); ++iter )
 {  
  cout << iter->first << " ";
 }
 cout << endl;
   
 return 0;
}

Copyright@戴维 2006.4  于北京

2 硬件工程师笔面试高频知识考点真题解析——电容 本文全面解析了电容在电子电路中的关键应用与技术要点。主要内容包括:1. 电容选型核心要素:介质材质(陶瓷/电解/钽电容等)、容值精度、耐压等级、温度特性、ESR参数等,不同应用场景(滤波/去耦/谐振等)的选型策略。2. 典型电路应用原理:详细阐述去耦电容布局规则、晶振负载电容作用、共射放大电路旁路电容功能,以及RC电路的滤波/定时等应用。3. 特殊问题解决方案:MLCC啸叫机理与对策、寄生电容影响与消除、高速信号线电容使用禁忌等工程实践难题。4. 安全规范要点:X/Y电容的区别与选用、电解/钽电容防反接措施 阅读详情

相关推荐

Fluent求解器——湍流参数的设置

Fluent湍流参数的介绍和设置。

Ronko_G的博客 4万+

【Java集合】Iterator迭代器remove()的使用以及使用foreach循环遍历集合元素

1、 Iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方 法,不是集合对象的remove方法。

qq_64976935的博客 2095

RoCE Overlay

1. RoCE over vxlan 配置vxlan封装的RoCE流量,可以在PF switchdev模式下利用ovs bridge,或直接设置tc rules。下面将基于一对NIC互联的服务器介绍两种方式的使用,并分析封装后的数据包结构。 1.1. 基本配置 - VF与switchdev 首先创建VF,并为两个host设置PF的switchdev模式。使用ovs bridge或tc rules,...

sunshuying1010的博客 3061

深入理解集合的迭代器 Iterator,为什么遍历数组时删除元素不能直接使用remove()方法而需要使用迭代器?

本文介绍了Java中Iterator迭代器的基本概念与使用方法。主要内容包括:1. Iterator接口的核心方法hasNext()和next()的作用;2. 通过ArrayList示例演示迭代器的创建与遍历过程;3. 使用迭代器时的注意事项:不会报索引越界异常、不会自动复位、每次循环只能调用一次next()方法、遍历时不能使用集合方法修改集合元素。文章重点解析了迭代器遍历时修改集合会抛出ConcurrentModificationException异常的底层原理(modCount机制)。

m0_70325779的博客 3014

如何修复Windows卡在“正在准备Windows”的问题?这里有详细步骤

如何修复Windows卡在“正在准备Windows”的问题?这里有详细步骤。

wyxtx的博客 5662

全网详细解决:无法将 “xxx” 项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次

全网详细解决:无法将 “xxx” 项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。

念兮为美 5万+

Java Iterator 迭代器 遍历、删除元素

Iterator 迭代器 迭代器遍历方式, 适用于连续内存存储方式,比如数组、 ArrayList(其实 ArrayList底层实现也是数组形式)。 缺点是只能从头开始遍历, 优点是可以边遍历边删除 arraylist每次遍历的时候会去判断该集合是否被修改过,调用的方法是checkForComodification()。 如果被修改过ConcurrentModificationException异常。 如何判断是否修改呢,主要是通过维护2个变量来实现,modCount记录了修改次数,expectedMod

weixin_42408447的博客 5188

Windows 11 WSL2环境下OpenClaw部署的兼容性问题分析与解决方案研究

本文研究了OpenClaw在Windows 11 WSL2环境下的部署方案。WSL2通过无缝集成Linux与Windows系统,为OpenClaw提供了良好的运行环境,支持GPU加速和跨平台开发。文章详细分析了硬件配置要求(推荐8核CPU/16GB内存/NVMe SSD)、系统选择(Windows 11 Pro+Ubuntu 22.04)以及部署步骤,包括WSL2启用、Linux发行版安装、Python/Node.js/Redis等依赖配置。通过优化.wslconfig文件参数(如内存分

博客 2279

Java基础(二):迭代器(Iterator)(含使用方法详解)

Java Iterator(迭代器) Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayList 和 HashSet 等集合。 Iterator 是 Java 迭代器最简单的实现,ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口。 迭代器 it 的两个基本操作是 next 、hasNext 和 remove。 调用 it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态。 调用 it.ha

Viper的程序员修炼手册 2万+

YOLO26改进目录一览 | 涉及卷积层、轻量化、注意力、损失函数、Backbone、SPPF、Neck、检测头等全方位改进

1️⃣ 什么!不知道如何改进模型⁉️ 本专栏已更新260多种不同的改进方法,所使用并改进的每一个模块均包含详细的模块分析、原理讲解、个人总结、多种改进方式以及完整的修改流程,所有改进100%可直接运行,性价比极高。2️⃣ 找不到合适的模块⁉️ 所有改进点均为近三年顶会,顶刊提出的先进算法,将其融入到中,并进行二次创新,新颖度高,创新度高,能够适应不同的任务场景。3️⃣ 不确定自己改进的步骤、结果是否正确⁉️ 订阅专栏即可进群享受模型训练、模型改进、论文写作、投稿选刊,从入门到论文的各种答疑内容,非常适合新手

Limiiiing的博客 6342

Python开发MCP Client

全部例子只是MCP Client访问MCP Server的过程,那么这样其实就失去了MCP协议的创建的初衷,和大模型集成后才能发挥MCP最大的作用。

Criss@陈磊 2973

使用Iterator迭代器删除元素

java.util.Iterator迭代器中有一个方法:那么,既然Collection已经有remove(xx)方法了,为什么Iterator迭代器还要提供删除方法呢?因为在JDK1.8之前Collection接口没有removeIf方法,即无法根据条件删除。例如:要删除以下集合元素中的偶数。

weixin_46074865的博客 2828

如何使用迭代器iterator循环删除容器中的元素?

STL中任何容器都可以使用迭代器进行元素的遍历,当需要在遍历中删除某些元素时,容器中元素的布局(位置或者排序)会随之改变,当前迭代器所指示的元素也会发生变化,这时继续递增或者递减迭代器进行后续元素的遍历时就要特别小心。容器的元素删除方法很大程度上依赖于操作系统上STL的实现版本,不同的系统和STL版本均有不同的定义。详见正文分析。 STL中的容器主要分两类,一是顺序存储的,

超空间 1万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java-Iterator迭代器

迭代指的是重复的过程,这个接口就是来定义被重复执行的一个过程的标准。为啥需要这个东西呢?Collection的两个子类List和Set,在迭代List和Set时,使用的方式不同,List用有迭代因子来进行迭代,Set用for-each迭代,两个容器的迭代方式不同,为了统一,使用Iterator迭代器,对List和Set统一进行迭代。 单例集合实现了Iterator接口,在该接口中包含一个名为iterator的抽象方法,所有实现了Collection接口的容器类对该方法做了具体实现。iterator方法会返

lipengfei0427的博客 591

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Java-容器-Iterator迭代器接口

Collection接口继承了Iterable接口,在该接口中包含一个名为iterator的抽象方法,所有实现了Collection接口的容器类对该方法做了具体实现。iterator方法会返回一个Iterator接口类型的迭代器对象,在该对象中包含了三个方法用于实现对。

2402_88479893的博客 393

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Iterator接口

梳理Iterator类的相关知识

Eliauk_Doubling的博客 528

1 Iterator迭代器

1.1 Iterator迭代器接口介绍 Collection接口继承了Iterator接口,在该接口中包含一个名为iterator的抽象方法,所以有实现了Collection接口的容器类对该方法做了具体实现。iterator方法返回一个Iterator接口类型的迭代器对象,在该对象中包含了三个方法用于实现对单例容器的迭代器处理。 Iterator迭代器接口作用:通过迭代器当中所定义标准的行为来对不同类型的容器采用相同的方法遍历它们。 1.1.1 迭代器的使用 使用Iterator...

零基础学java 236

Iterator迭代器

Iterator迭代器 一、Iterator迭代器接口介绍 二、Iterator容器的使用 /** * 迭代List接口类型容器 */ import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Iterator_List_Test { public static void main(String[] args) { //实例化容器 List<String&gt

qq_44733777的博客 100

【编程语言】Java 迭代器

Java 迭代器 使对容器内元素的操作更为简单,Java引入了迭代器模式! 把访问逻辑从不同类型的集合类中抽取出来,从而避免向外部暴露集合的内部结构。 下面两段代码分别对“数组”和“ArrayList”进行遍历,可以看见这种遍历方式是与被遍历对象的类型紧密耦合,无法将访问逻辑从集合类和客户端代码中分离出来。不同的集合会对应不同的遍历方法,客户端代码无法复用。在实际应用中如何将上面两个集合整合是相当...

ss的程序人生 1948

使用 Iterator 接口遍历集合元素

学习

qq_52589245的博客 257

JavaSE 学习参考:迭代器

迭代器(Iterator)是可以遍历和查找集合容器中的对象,使用者无需了解集合的内部结构。通常集合容器都提供迭代器接口的实现,作为内部内部类来实现具体数据结构操作算法。   Java中定义Iterator接口,功能比较简单,并且只能单向向后移动,功能如下: iterator()要求集合容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回集合容器的第一个元素。

bwf_erg的博客 283

java:迭代器Iterator

迭代器Iterator是一个对象,它的工作是遍历并选择序列中的对象,它提供了一种访问一个容器(container)对象中的各个元素,而不必暴露该对象内部细节的方法。 通过容器的 iterator()方法得到迭代器。通过迭代器遍历容器元素。 迭代器Iterator的主要方法: hasNext(), 判断容器中是否还有元素 next(), 获取容器的元素 ...

m0_37564426的博客 240

java集合框架中迭代器的作用_Java 集合框架的迭代器

Java的容器ArrayList、LinkedList、HashSet等可遍历容器,因为不想暴露底层结构,都会实现一个迭代器用于遍历容器。Iterator接口Iterator接口是迭代器的顶层接口,接口方法很简单,就是单向遍历和删除元素:Iterator {boolean hasNext();E next();void remove();forEachRemaining(action);}List...

weixin_33269198的博客 388

CopyOnWriteArrayList和ArrayList遍历和删除操作区别

复制出一个新的容器,然后在这个新的容器里进行修改元素的操作,而后面进行的读操作则继续在旧容器中读取。修改完之后,再将原容器的引用指向新的容器,而旧的容器则进行垃圾回收。对一个容器进行修改操作(添加、删除、编辑)时候,不会直接对当前容器修改,而是先将当前容器进行 Copy,CopyOnWrite 原理。

stand up 674

Kotlin-容器Set的三种遍历方式

#Set的三种遍历方式 ##声明变量,将变量添加至容器,以及从容器中删除变量。 private val goodsA:String = "iphone11pro" private val goodsB:String = "oppo" private val goodsC:String = "华为" private val goodsD:String = "小米" private val goodsE:String = "三星" private val goodsF:String = "vivo" priva

weixin_45811645的博客 1132
上一篇: 如何使用fstream类在读写操作之间任意转化?
下一篇: 关于N皇后问题高效试探回溯算法的分析
sharpdew
博客等级 码龄23年 76粉丝 35原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值