ArrayList在for循环中使用remove方法移除元素方法介绍
作者:性子有点污 发布时间:2022-11-20 03:50:18
有时候我们需要在一个ArrayList的for循环中动态删除元素的需求, 废话不多说看代码
List<Integer> list = new ArrayList<Integer>();
list.add(0);
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
//正常循环
for (int i = 0; i < list.size(); i++) {
System.out.println("i的值:" + i + " 对应的数字:" + list.get(i));
}
System.out.println("没有remove前list的项:"+list.size());
//边循环边删除
for (int i = 0; i < list.size(); i++) {
System.out.println("i的值:" + i + " 对应的数字:" + list.get(i));
if(list.get(i) == 3) list.remove(list.get(i));//删除list的第四项
}
System.out.println("remove后list的项:"+list.size());
System.out.println("==========remove后的list==========");
for (int i = 0; i < list.size(); i++) {
System.out.println("i的值:" + i + " 对应的数字:" + list.get(i));
}
执行代码, 结果如下:
i的值:0 对应的数字:0
i的值:1 对应的数字:1
i的值:2 对应的数字:2
i的值:3 对应的数字:3
i的值:4 对应的数字:4
i的值:5 对应的数字:5
i的值:6 对应的数字:6
i的值:7 对应的数字:7
没有remove前list的项:8
i的值:0 对应的数字:0
i的值:1 对应的数字:1
i的值:2 对应的数字:2
i的值:3 对应的数字:3
i的值:4 对应的数字:5
i的值:5 对应的数字:6
i的值:6 对应的数字:7
remove后list的项:7
==========remove后的list==========
i的值:0 对应的数字:0
i的值:1 对应的数字:1
i的值:2 对应的数字:2
i的值:3 对应的数字:4
i的值:4 对应的数字:5
i的值:5 对应的数字:6
i的值:6 对应的数字:7
可以看到没有删除前, 我们的list的项和循环对应的数字都是正确的, 但是下面的循环在删除第4个元素后,第4,5,6个项对应的数字本应该是4,5,6, 但是这里却变成了5,6,7.
原因是,我们删除第4项后,list的长度就变成7,而且,list会把第4项后面的值往前移一位, 也就是说,i=3时,list.get(i)=4,i=4时,list.get(i)=5,i=5时,list.get(i)=6,i=6时,list.get(i)=7.. 我们再说的形象一点, 就是本来有8层糕点,依次是0-7,竖起来,大的在上,小的在下,我们从下往上数,数到第5个的时候,吃掉这一层糕点,这时,上面三层分别往下移了一层
所以, 值为4的项我们根本没有循环到
那有什么方法可以实现remove呢, 有个笨方法,是新建一个tempList, 把要删除的项全部add进去,最后用list.removeAll(tempList)实现 . 但是这里我们有更好的方法, 就是倒序删除
还是上面的例子, 我们看代码:
List<Integer> list = new ArrayList<Integer>();
list.add(0);
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
//正常循环
for (int i = 0; i < list.size(); i++) {
System.out.println("i的值:" + i + " 对应的数字:" + list.get(i));
}
System.out.println("没有remove前list的项:"+list.size());
//边循环边删除
for (int i = list.size() -1 ; i >= 0; i--) {
System.out.println("i的值 " + i + " 对应的数字 " + list.get(i));
if(list.get(i) == 3) list.remove(list.get(i));
}
System.out.println("remove后list的项:"+list.size());
System.out.println("==========remove后的list==========");
for (int i = 0; i < list.size(); i++) {
System.out.println("i的值 " + i + " 对应的数字 " + list.get(i));
}
执行代码,结果如下:
i的值:0 对应的数字:0
i的值:1 对应的数字:1
i的值:2 对应的数字:2
i的值:3 对应的数字:3
i的值:4 对应的数字:4
i的值:5 对应的数字:5
i的值:6 对应的数字:6
i的值:7 对应的数字:7
没有remove前list的项:8
i的值 7 对应的数字 7
i的值 6 对应的数字 6
i的值 5 对应的数字 5
i的值 4 对应的数字 4
i的值 3 对应的数字 3
i的值 2 对应的数字 2
i的值 1 对应的数字 1
i的值 0 对应的数字 0
remove后list的项:7
==========remove后的list==========
i的值 0 对应的数字 0
i的值 1 对应的数字 1
i的值 2 对应的数字 2
i的值 3 对应的数字 4
i的值 4 对应的数字 5
i的值 5 对应的数字 6
i的值 6 对应的数字 7
我们可以看到变循环变删除,并不影响后面的元素, remove后的list也和第一次的结果是一样的 . 这是因为我们删除list元素,list的长度是会变小, 但是变化的只是比当前被删除元素的项大的项, 而我们这里使用倒序循环, 大的项, 我们已经执行过了, 所以不会影响.. 再用上面的比喻来说明,这次我们是从上往下数,数到第4个的时候,吃掉这一层糕点,这时,上面三层分别往下移了一层 , 但是这不影响我们之前数过的蛋糕, 而且对下面的蛋糕也不影响, 这就是原理
来源:http://blog.csdn.net/u012316120/article/details/51509066


猜你喜欢
- 1. 线程转储简介线程转储(Thread Dump)就是JVM中所有线程状态信息的一次快照。线程转储一般使用文本格式, 可以将其保存到文本文
- /*最小树形图图模版-朱刘算法模版说明:点标号必须0-(N-1) 必须去除到自身的点(到自身的边的边权赋无限大)*/
- 得到选中项的value值并拼接成一个字符串返回public string GetChecked(CheckBoxList checkList
- 这篇文章从系统源代码分析,讲述如何将程序创建的多媒体文件加入系统的媒体库,如何从媒体库删除,以及大多数程序开发者经常遇到的无法添加到媒体库的
- 在C#中调用C(C++)类的DLL的时候,有时候C的接口函数包含很多参数,而且有的时候这些参数有可能是个结构体,而且有可能是结构体指针,那么
- 前言本文简单介绍抽象类,接口以及它们的异同点,另附简单的代码举例。一、抽象类是什么?在 Java 语言中使用 abstract class
- 该方法使用的jdk1.6以后自带的分页工具类实现public static void main(String[] args) {  
- 可能导致问题的原因:1.nacos中的配置文件名不规范,官网有命名规则:“前缀”-&ldqu
- 概述从今天开始, 小白我将带大家开启 Jave 数据结构 & 算法的新篇章.循环队列循环队列 (Circular Queue) 是一
- kafka消费不到数据的排查集群上新安装并启动了3个kafka Broker,代码打包上传至集群,运行后发现一直消费不到数据,本地
- 本文介绍了Spring Boot 与DBunit 配合使用方法,分享给大家,具体如下:DBUnit快速上手Springboot 添加 DBu
- 定义一个对象应该对其他对象保持最少的了解。问题由来类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。解决方案尽
- 前言:在Java项目中,有两个主要的构建系统:Gradle和Maven。构建系统主要管理潜在的复杂依赖关系并正确编译项目。还可以将已编译的项
- Spring中实现多线程,其实非常简单,只需要在配置类中添加@EnableAsync就可以使用多线程。在希望执行的并发方法中使用@Async
- 本文实例讲述了winform绑定快捷键的方法。分享给大家供大家参考。具体分析如下:第一种:Alt + *(按钮快捷键)在大家给button、
- Eclipse安装配置好之后,小千再来带大家进行基本的使用。1. 创建项目我们可以点击左上角的File-->New-->Proj
- **前言:**我们项目中可能有这种需求,每个人请求了哪些接口?做了什么事情?参数是什么?重要的接口我们需要记录操作日志以便查找。操作日志和系
- 系统自带的VideoView有些视频格式不支持,那么我们可以用第三方实现的VideoView替代系统的来播放视频,比较流行的有ijkplay
- RestTemplate设计是为了Spring更好的请求并解析Restful风格的接口返回值而设计的,通过这个类可以在请求接口时直接解析对应
- 使用Mybatis的开发者,大多数都会遇到一个问题,就是要写大量的SQL在xml文件中,除了特殊的业务逻辑SQL之外,还有大量结构类似的增删