对List遍历过程中添加和删除的思考
对List遍历过程中添加和删除的思考
平时开发过程中,不少开发者都遇到过一个问题:在遍历集合的的过程中,进行add或者remove操作的时候,会出现2类错误,包括:
java.util.ConcurrentModificationException for in遍历过程中add/remove导致的错误
java.lang.IndexOutOfBoundsException 越界错误,for循环的时候删除元素。
最佳实践
add操作:利用原生的for循环。remove操作利用foreach操作。如下所示:
//OK,利用 iterator 和 其remove 方法
@Test
public void testIteratorRemove2() {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
if ("3".equals(iterator.next())) {
iterator.remove();
}
}
System.out.println(list);
}
//OK 利用for循环。
@Test
public void testForAdd() {
for (int i = 0, length = list.size(); i < length; i++) {
if (list.get(i).equals("2")) {
list.add("2");
}
}
}
经典错误1
如下代码本意是:通过iterator的方式从头到尾变遍历list中的元素。
@Test
public void testIteratorRemove2() {
while (list.iterator().hasNext()) {
System.out.println(list.iterator().next());
}
}
但是该段代码永远都会输出 list的第一元素,为什么?关键错误在链式写法上:
while (list.iterator().hasNext()) {}
每次循环时候先调用了list.iterator() 在该方法中每次都是重新new了一个新的对象
public Iterator<E> iterator() {
return new Itr();
}
所以每一次都是一个新的遍历对象,所以输出第一个元素。
那么为什么每次都要new一个新的Itr()?我猜想应该是为了并发的读,每次读的都是一份独立的数据,避免多个并发读的时候,出现当前指针问题。
处理办法:将list.iteraotr() 放在外面即可,保证循环中循环的是1个对象。
@Test
public void testIteratorRemove2() {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
if ("3".equals(iterator.next())) {
iterator.remove();
}
}
System.out.println(list);
}
经典错误2
// 死循环
@Test
public void testForAdd2() {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals("3")) {
list.add("3");
}
}
}
当if条件满足的时候,该方法永远不会结束,为什么?
对于for循环 for (int i = 0; i < list.size(); i++)有3个部分,第一个部分为初始化,只执行一次。第二个部分每次都会执行,第三个部分也是每次都会执行。
上述问题的第二步会导致无限循环:因为for中每一次循环都会在list添加了一个元素,每次步进为1,内部元素也是每次都加1.
如何处理该问题: list.size()放在第一部分,第一部分只初始化一次。
//OK 利用for循环。
@Test
public void testForAdd() {
for (int i = 0, length = list.size(); i < length; i++) {
if (list.get(i).equals("2")) {
list.add("2");
}
}
}
经典错误3
//java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
@Test
public void testForRemove() {
for (int i = 0, length = list.size(); i < length; i++) {
if (list.get(i).equals("3")) {
list.remove("3");
}
}
}
该错误在list.add("3")的时候就不会发生该错误,具体原因是什么?
Liu CF:转载请保留原文链接,3Q!
对List遍历过程中添加和删除的思考的更多相关文章
- JavaScript向select下拉框中添加和删除元素
JavaScript向select下拉框中添加和删除元素 1.说明 a 利用append()方法向下拉框中添加元素 b 利用remove()方法移除下拉框中最后一个元素 2.设计源码 < ...
- 怎样Zbrush 4R7中添加和删除SubTool
添加或删除SubTool在ZBrush®软件中是非常简单易操作的,通常在用SubTool面板已经给我们提供了相应的命令来对其进行操作,它能够将一个或多个格式为ZTL的文件同时添加进SubTool里. ...
- MySql中添加用户/删除用户
MySql中添加用户,新建数据库,用户授权,删除用户,修改密码(注意每行后边都跟个;表示一个命令语句结束): 1.新建用户 登录MYSQL: @>mysql -u root -p @>密码 ...
- MySQL中添加、删除约束
MySQL中6种常见的约束:主键约束(primary key).外键约束(foreign key).非空约束(not null).唯一性约束(unique).默认值约束(defualt).自增约束(a ...
- vector容器中添加和删除元素
添加元素: 方法一: insert() 插入元素到Vector中 iterator insert( iterator loc, const TYPE &val ); //在指定位置loc前插入 ...
- vue中添加与删除,关键字搜索
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 在Ubuntu中添加和删除PPA的软件源
PPA,英文全称为 Personal Package Archives,即个人软件包档案.是 Ubuntu Launchpad 网站提供的一项源服务,允许个人用户上传软件源代码,通过 Launchpa ...
- 利用JS实现在li中添加或删除class属性
$( function() { $("#test li").click(function(){ $("#test li").removeClass(" ...
- 原生js事件的添加和删除
在IE浏览器中添加或删除事件用attachEvent.detachEvent.在其他标准浏览器中则用addEventListener.removeEventListener.下面的对事件的添加和删除做 ...
随机推荐
- Yii2 组件
组件的命名空间: 响应组件: yii\web\Response Yii预定义的HTTP异常组件: yii\web\BadRequestHttpException: //状态码 400. yii\web ...
- C# 哈希表HashTable的简单使用
本人C#程序菜鸟级别的存在,写博客一方面是为了知识的共享,另一方面也是为了督促自己:大神,可以忽略这篇文文的.废话到此...... 哈希表是可以直接进行访问的数据结构,在形式上是类似字典的.不同的是, ...
- PAT Basic 1046
1046 划拳 (15 分) 划拳是古老中国酒文化的一个有趣的组成部分.酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字.如果谁比划出的数字正好等于两人喊出的数字之和,谁就赢了,输 ...
- JWTtoken的原理以及在django中的应用
JWT 在用户注册或者登陆完成之后,记录用户状态,或者为用户创建身份凭证(功能类似于session的作用). 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而 ...
- Mac删除默认美国输入法
1.打开sudo open ~/Library/Preferences/com.apple.HIToolbox.plist 2.找到这个,然后点击删除,最后保存,然后在立马重启 3.如果要还原,直接在 ...
- aix 查看内存,CPU 配置信息
内存lsattr -El mem0cpu lsdev -C |grep procCPU的信息lsattr -El proc0 #bootinfo -r查看物理内存 使用命令# lsdev ...
- Asp.NET WebApi+Redis实现单用户登录实战演练
一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理和 ...
- Docker实现容器具有固定IP
Docker的网络类型 Docker安装后,默认会创建三种网络 $ docker network ls NETWORK ID NAME DRIVER SCOPE 6bdc00ad2a8d bridge ...
- ASP.NET 使用 plupload 上传大文件时出现“blob”文件的Bug
最近在一个ASP.NET 项目中使用了plupload来上传文件,结果几天后客户发邮件说上传的文件不对,说是文件无法打开 在进入系统进行查看后发现上传的文件竟然没有后缀,经过一番测试发现如果文件上传的 ...
- python写入excel(xlswriter)--生成图表
一.折线图: # -*- coding:utf-8 -*- import xlsxwriter # 创建一个excel workbook = xlsxwriter.Workbook("cha ...