java 对list增删_List 中正确的增删操作

这个为什么要单独说的原因是,在开发中的对数据库中的增删为最基本的,但是是不是写对了就尤为重要

先来看代码:

1 public voidtestLoopInList(){2 List a = new ArrayList();3 a.add("1");4 a.add("2");5 a.add("w");6 for(String string : a) {7 System.out.println(string);8 }9

10 for(String temp : a) {11 if("2".equals(temp)){12 a.remove(temp);13 }14 }15

16 for(String string : a) {17 System.out.println(string);18 }

输出:

1

2java.util.ConcurrentModificationException

at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)

at java.util.ArrayList$Itr.next(ArrayList.java:831)

at test.Test_ForeachAndIterator.testLoopInList(Test_ForeachAndIterator.java:19)

出现错误了

原因:首先从错误中可以看出,是ArraList中的Iterator的checkForComodification()出现的错误,说明了foreach的实现原理其实就是实现了内部类I特Iterator来进行遍历的,其次为什么会出错呢?

因为在ArrayList和ArrayList的内部类的Iterator中的都会存在remove的方法,而ArrayList和Iterator中都各自有自己的维持长度的变量,前者是modCount,后者是expectModCount,但是源码中ArrayList的remove方法是会改变modCount的值,但却不会直接同步到expectModCount的值的,而Iterator中时刻都插入了checkForComodification()方法来监测modCount是否与expectModCount相等,所以就会很容易出现异常错误,当然下面的代码也是错的

1 public voidtestLoopInList(){2 List a = new ArrayList();3 a.add("1");4 a.add("2");5

6 for(String string : a) {7 System.out.println(string);8 }9

10 Iterator it =a.iterator();11 while(it.hasNext()){12 if("1".equals(it.next())){13 a.remove(it.next());14 }15 }16

17 for(String string : a) {18 System.out.println(string);19 }20 }

错误原因同上

所以在解决问题的关键就是要避免这个异常的出现,也就是时刻让modCount==expectModCount,所以就是使用iterator的remove方法,因为会有使两者相等的代码

即下面:

1 public voidtestLoopInList(){2 List a = new ArrayList();3 a.add("1");4 a.add("2");5

6 for(String string : a) {7 System.out.println(string);8 }9

10 Iterator it =a.iterator();11 while(it.hasNext()){12 if("1".equals(it.next())){13 it.remove();14 }15 }16

17 for(String string : a) {18 System.out.println(string);19 }20 }

相关源码提上:

1 private class Itr implements Iterator{2 /**

3 * Index of element to be returned by subsequent call to next.4 */

5 int cursor = 0;6 /**

7 * Index of element returned by most recent call to next or8 * previous. Reset to -1 if this element is deleted by a call9 * to remove.10 */

11 int lastRet = -1;12 /**

13 * The modCount value that the iterator believes that the backing14 * List should have. If this expectation is violated, the iterator15 * has detected concurrent modification.16 */

17 int expectedModCount =modCount;18 public booleanhasNext() {19 return cursor !=size();20 }21 publicE next() {22 checkForComodification();23 try{24 E next =get(cursor);25 lastRet = cursor++;26 returnnext;27 } catch(IndexOutOfBoundsException e) {28 checkForComodification();29 throw newNoSuchElementException();30 }31 }32 public voidremove() {33 if (lastRet == -1)34 throw newIllegalStateException();35 checkForComodification();36 try{37 AbstractList.this.remove(lastRet);38 if (lastRet

ArrayList中的remove

1 public booleanremove(Object o) {2 if (o == null) {3 for (int index = 0; index < size; index++)4 if (elementData[index] == null) {5 fastRemove(index);6 return true;7 }8 } else{9 for (int index = 0; index < size; index++)10 if(o.equals(elementData[index])) {11 fastRemove(index);12 return true;13 }14 }15 return false;16 }

当然你说我不用for增强,就用普通的for ,就不会有创建Iterator的操作,进而就不会有Iterator的实时监测维护值得操作,也行啊,但还是要注意有坑啊! 比如我们来看下面的代码:

1 List list = newArrayList();2 Collections.addAll(list, 1, 2, 3, 4, 5);3 for(int i = 0; i < list.size(); ++i){4 int val = (int) list.get(i);5

6 //需求是删除 3 和 4 两个元素

7 if(3 == val || 4 ==val){8 list.remove(i);9 }10 }

这是我们非常常见的写法,结果 为 :1 2 3 4

奇怪了,4为甚没有删除掉,其实仔细想想 还是能相同的 删除了3之后 i = 3 size = 4,这时候,list.get返回值为5, 会跳过4

所以 修改的话,两个 liter tips : 要么自己维护索引,要么反向循环

1 for(int i = list.size() - 1; i > 0; --i){2 int val = (int) list.get(i);3

4 //需求是删除 3 和 4 两个元素

5 if(3 == val || 4 ==val){6 list.remove(i);7 }8 }

1 for(int i = 0; i < list.size(); ++i){2 int val = (int) list.get(i);3

4 //需求是删除 3 和 4 两个元素

5 if(3 == val || 4 ==val){6 list.remove(i);7 i --; //删除后,索引也应该变化

8 }9 }

ok, that's all ...

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leedcode7-binary-tree-postorder-traversal

#include<iostream> #include<vector> #include<stack> using namespace std; // Definition for binary tree 先序遍历 根左右 struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; #if 0 c…

mysql zrm_mysql数据库备份—ZRM

ZRM是Zmanda Recovery Manager的缩写&#xff0c;这是一款备份mysql的开源软件。一、安装#yum install -y MySQL-zrm二、创建备用用户#mysql -uroot -pmysql>grant select,insert,update,create,drop,reload,shutdown,alter,super,lock table,replication client on *.* …

用tensorflow搭建RNN(LSTM)进行MNIST 手写数字辨识

用tensorflow搭建RNN(LSTM)进行MNIST 手写数字辨识 循环神经网络RNN相比传统的神经网络在处理序列化数据时更有优势&#xff0c;因为RNN能够将加入上&#xff08;下&#xff09;文信息进行考虑。一个简单的RNN如下图所示&#xff1a; 将这个循环展开得到下图&#xff1a; 上一…

java gzip rest_RestTemplate与Gzip压缩

Gzip 是一种压缩算法&#xff0c;服务器经常通过这个算法来压缩响应体&#xff0c;再响应给客户端&#xff0c;从而减少数据体积&#xff0c;提高传输速度。客户端再通过Gzip解压缩&#xff0c;获取到原始的数据。因为需要压缩计算&#xff0c;所以会耗费额外的CPU资源。Gzip 与…

RNN入门

雷锋网 AI科技评论按&#xff1a;本文作者何之源&#xff0c;原文载于知乎专栏AI Insight&#xff0c;雷锋网(公众号&#xff1a;雷锋网) AI科技评论获其授权发布。 上周写的文章《完全图解RNN、RNN变体、Seq2Seq、Attention机制》介绍了一下RNN的几种结构&#xff0c;今天就来…

Java二进制小数表示_《Java编程的逻辑》笔记9--小数的二进制表示

小数计算为什么会出错&#xff1f;简要答案实际上&#xff0c;不是运算本身会出错&#xff0c;而是计算机根本就不能精确的表示很多数&#xff0c;比如0.1这个数。计算机是用一种二进制格式存储小数的&#xff0c;这个二进制格式不能精确表示0.1&#xff0c;它只能表示一个非常…

『TensorFlow』模型保存和载入方法汇总

一、TensorFlow常规模型加载方法 保存模型 tf.train.Saver()类&#xff0c;.save(sess, ckpt文件目录)方法 参数名称功能说明默认值var_listSaver中存储变量集合全局变量集合reshape加载时是否恢复变量形状Truesharded是否将变量轮循放在所有设备上Truemax_to_keep保留最近检…

STL13-list容器(链表)

链表是由一系列的结点组成&#xff0c;结点包括两个域&#xff1a;一个数据域&#xff0c;一个指针域 1、链表内存是非连续的&#xff0c;添加删除元素效率较高&#xff0c;时间复杂度都是常数项&#xff0c;不需要移动元素 2、链表只有在需要的时候才会分配内存 3、链表只要…

java调用el_[Java教程][javaEE] EL表达式调用java方法

[Java教程][javaEE] EL表达式调用java方法0 2016-07-03 18:00:031.新建个类&#xff0c;类里面定义静态方法package com.tsh.utils;import java.net.URLEncoder;public class ELFunc { public static String urlEncode(String str){ return URLEncoder.encode(str); }}2.在WEB-…

Leedcode8-reorder-list

#include<iostream> #include<vector> using namespace std; //Definition for singly-linked list. /*Given a singly linked list L : L 0→L 1→…→L n - 1→L n, reorder it to : L 0→L n →L 1→L n - 1→L 2→L n - 2→…*/ struct ListNode {int val;List…

java设计是什么软件下载_用Java设计下载软件

用Java设计下载软件HTTP 协议的简介HTTP协议是一种超文本传输协议(Hypertext Transfer Protocol)&#xff0c;工作于网络应用层&#xff0c;自1990年起广泛应用于WWW 的全球信息服务&#xff0c;HTTP协议的具体说明可以在网上查阅RFC2518、RFC2616等文档。HTTP 协议老的标准是H…

php 前往页面,PHP实现网页截图?

如何使用PHP实现网页截图PHP实现网页截图是一个在日常开发中不常见的需求&#xff0c;但是如果实现还是非常有意思的。目前业界有很多成熟的方案&#xff0c;下面我推荐使用一个很稳定的第三方服务来直接实现&#xff0c;该服务有如下特点&#xff1a;支持多线路支持登录截图支…

Leedcode9-linked-list-cycle-i

判断链表是不是循环链表 #include<iostream> #include<vector> using namespace std; /* Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using extra space?*/ struct ListNode {int val;ListNode *next;ListNo…

Leedcode10-linked-list-cycle-ii

判断是不是循环链表&#xff0c;如果是&#xff0c;返回它的第一个结点 首先判断&#xff0c;判断完之后&#xff0c;遍历循环链表&#xff0c;将它的指针域置为空&#xff0c;则循环到链表的第一个结点时&#xff0c;由于指针域为空&#xff0c;返回 #include<iostream&g…

STL14-set/multiset容器

set只有一个方法就是insert #include<iostream> #include<set> //set和multiset是一个头文件 //set内部实现机制 红黑色&#xff08;平衡二叉树的一种&#xff09; //关联式容器 //set不允许有重复元素 //multiset运行有重复元素 //容器查找效率高 //容器根据元素的…

普通的java类型是指,String是一个很普通的类 - Java那些事儿

上一篇我们讲了Java中的数组&#xff0c;其实是为本章的内容做准备的&#xff0c;String这个类是我们在写Java代码中用得最多的一个类&#xff0c;没有之一&#xff0c;今天我们就讲讲它&#xff0c;我们打开String这个类的源码&#xff1a;声明了一个char[]数组&#xff0c;变…

STL15-map/multimap容器

map的key值不可以重复 multimap的key值可以重复 #if 1 #include<iostream> #include<map> using namespace std; //初始化 void test01() {//map容器参数 第一个参数key的类型 第二个参数value类型map<int, int> mymap;//插入元素 pair.first key值 pair.se…

php nginx日志分析,如何通过NGINX的log日志来分析网站的访问情况,试试这些命令...

想知道你的网站每天的访问情况吗&#xff1f;有多少人访问了&#xff1f;访问最多的页面是哪个&#xff1f;哪个时段访问的人最多&#xff1f;哪个地方访问的最多&#xff1f;每秒有多少请求&#xff1f;很好奇吧&#xff0c;只要你是使用了nginx进行请求抓发&#xff0c;那么就…

ajax获取表单php,Yii2基于Ajax自动获取表单数据的方法

本文实例讲述了Yii2基于Ajax自动获取表单数据的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;这里有两张表&#xff0c;表结构如下&#xff0c;locations表存放的省份和邮编等信息&#xff0c;两张表的model和curd均使用gii生成yii2advanced.customers表custome…

php response响应,9. 响应 (Response)

## 为什么单独创建一个Response?跟为什么要单独创建一个Request 一样。原因: 可以管理如: 在 swoole 不应该用 echo, 因为 swoole 是 cli 运行,只会输出在命令行。必须 只有一个地方能 输出响应 就是此篇的功能确保有 集中控制权 是非常重要 !(后面代码有 echo 都是不规范的, …