在工作中的许多场景下,我们都会使用到List这个数据结构,那么同样的有很多场景下需要删除List中的某一个元素或某几个元素,那么我们该如何正确无误地删除List中的元素的,今天我来教大家三种方式。

前提知识准备

for循环的执行顺序

这里借用百度百科的一张图,简明扼要的介绍一下。

Iterator迭代器介绍

迭代器:迭代其实我们可以简单地理解为遍历,是一个标准化遍历各类容器里面的所有对象的方法类,它是一个很典型的设计模式。Iterator 模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向每次遍历前都需要知道要遍历集合的内部结构。

// 遍历list
List list = new ArrayList();
list.add(1);
list.add(2);
for (int i = 0; i < list.size(); i++) {
Object object = list.get(i);
// do something
} // 遍历map
Map<String,String> map = new HashMap<>();
map.put("1","first");
map.put("2","second");
for (Map.Entry<String,String> entry : map.entrySet()){
String key = entry.getKey();
String value = entry.getValue();
// do something
}

对于这两种方式,我们总是都事先知道集合的内部结构,访问代码和集合本身是紧密耦合的,无法将访问逻辑从集合类和遍历方法中分离出来。同时每一种集合对应一种遍历方法,代码无法复用。
为了解决以上问题, Iterator 模式腾空出世,它总是用同一种逻辑来遍历集合。使得需要遍历集合的人,在遍历的时候不需要了解集合的内部结构,所有的内部状态都由 Iterator 来维护。遍历集合的方法不直接和集合类打交道,它总是控制 Iterator,向它发送”向前”,”向后”,”取当前元素”的命令,就可以间接遍历整个集合。

错误:for循环顺序遍历

直接使用简单for循环,以for (int i = 0; i < list.size(); i++) 进行遍历,这种方式可能会在遍历的过程中漏掉部分元素,从而出现少删的情况。

/**
* 通过简单的遍历方式,在遍历的过程中有可能会漏掉元素
* 取第二个元素i=1时,满足条件被删掉,原有的数组的第三个元素,变成了新数组的第二个元素
* i++后i=2,但i=2指向的是新数组中的第三个元素,那么原数组中的第三个元素就被漏掉了
*
* @param list
* @param element
* @return
*/
public static List forRemove(List list, Object element) {
for (int i = 0; i < list.size(); i++) {
if (element.equals(list.get(i))) {
list.remove(i);
}
}
return list;
}

错误:增强for循环,删除后不退出

使用增强for循环是,如果删除后继续向下循环则会报java.util.ConcurrentModificationException

/**
* 使用增强for循环是,如果删除后继续向下循环则会报
* java.util.ConcurrentModificationException
*
* @param list
* @param element
* @return
*/
public static List forceForRemove(List list, Object element) {
for (Object item : list) {
if (item.equals(element)) {
list.remove(item);
}
}
return list;
}

异常如下:

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at com.lingyejun.leetcode.RemoveListElement.forceForRemove(RemoveListElement.java:57)
at com.lingyejun.leetcode.RemoveListElement.main(RemoveListElement.java:112)

正确:逆向循环遍历

我们使用逆向遍历的方式可以得到正确的结果

/**
* 逆向循环,是正确的
* 1-->2-->3-->4
* 逆向循环时,倒数第一个元素满足条件被删除时,i--后,原数组的倒数第二个变成了新数组的倒数第一个元素
* i = size-2指向新数组的最后一个元素,没有漏掉。
* 同理倒数第二个元素满足条件被删除时,i--后,原数组的倒数第三个变成了新数组的倒数第二个元素
* i= size-3指向新数组的倒数第二个元素,也没有漏掉
*
* @param list
* @param element
* @return
*/
public static List reverseorRemove(List list, Object element) {
for (int i = list.size() - 1; i >= 0; i--) {
if (element.equals(list.get(i))) {
list.remove(i);
}
}
return list;
}

正确但不优雅:增强for循环删除元素后break

使用增强for循环,删除元素后,立即跳出,则正常退出,但缺点是不能向后继续循环了。  

/**
* 删除元素后,立即跳出,则正常退出,但不能向后继续循环了
*
* @param list
* @param element
* @return
*/
public static List forceForRemove1(List list, Object element) {
for (Object item : list) {
if (item.equals(element)) {
// 删除后立马终端循环,会正常跳出,但代价是不能继续向后循环了
list.remove(item);
break;
}
}
return list;
}

优雅删除:使用Iterator迭代器

使用迭代器可,正确无误的删除,代码简洁优雅,推荐使用!

/**
* 使用迭代器可,正确无误的删除
*
* @param list
* @param element
* @return
*/
public static List iteratorRemove(List list, Object element) {
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object cur = iterator.next();
if (cur.equals(element)) {
// 注意!!!这里时Iterator.remove()!!!而不是list.remove()!!!
iterator.remove();
}
}
return list;
}

参考文章:

https://jingyan.baidu.com/article/7f766dafaa6ee04101e1d0e6.html

http://wiki.jikexueyuan.com/project/java-enhancement/java-thirty.html

Java中如何优雅地删除List中的元素的更多相关文章

  1. Java 添加、替换、删除PDF中的图片

    概述 本文介绍通过java程序向PDF文档添加图片,以及替换和删除PDF中已有的图片.另外,关于图片的操作还可参考设置PDF 图片背景.设置PDF图片水印.读取PDF中的图片.将PDF保存为图片等文章 ...

  2. Java 添加、读取、删除Excel中的图表趋势线

    本文以Java示例介绍如何在Excel中添加趋势线,以及读取趋势线公式.通过文中的方法可支持添加6种不同类型的趋势线,包括Linear.Exponential.Logarithmic.Moving A ...

  3. MongoDB中如何优雅地删除大量数据

    删除大量数据,无论是在哪种数据库中,都是一个普遍性的需求.除了正常的业务需求,我们需要通过这种方式来为数据库"瘦身". 为什么要"瘦身"呢? 表的数据量到达一定 ...

  4. oracle中的rowid--伪列-删除表中的重复内容-实用

    1.rowid是一个伪列,是用来确保表中行的唯一性,它并不能指示出行的物理位置,但可以用来定位行. 2.rowid是存储在索引中的一组既定的值(当行确定后).我们可以像表中普通的列一样将它选出来. 3 ...

  5. 如何优雅地删除 Linux 中的垃圾文件

    不知道大家是否也跟我一样,是一只要把的自己电脑文件安排的条理有序,把没用的文件会及时删掉的程序猿呢?如果是的话,那么我们可以愉快地探讨下文章的内容.如果不是的话,你也可以留下来凑凑热闹嘛(>-& ...

  6. Linux中通过命令直接删除文件中最后一行

    何谓Sed(Stream EDitor):Sed原为UNIX系统上的非交谈式文字编辑器(non-interactive stream editor).当Sed读入待编辑文件,会依编辑命令来进行文件的编 ...

  7. 如何删除datatable中的一行数据

    在C#中,如果要删除DataTable中的某一行,大约有以下几种办法: 1,使用DataTable.Rows.Remove(DataRow),或者DataTable.Rows.RemoveAt(ind ...

  8. Java 8 中如何优雅的处理集合

    Java 8 中如何优雅的处理集合(Stream API) 在Java中,集合和数组是我们经常会用到的数据结构,需要经常对他们做增.删.改.查.聚合.统计.过滤等操作.相比之下,关系型数据库中也同样有 ...

  9. [java]删除数组中的某一个元素

    package org.company.project.test; import java.util.Arrays; import java.util.Scanner; public class Ar ...

随机推荐

  1. jvisualvm连接远程应用终于成功,附踩大坑记录!!(二:jmx方式)

    一.问题概述 参考前一篇: jvisualvm连接远程应用终于成功,附踩大坑记录!!(一:jstatd方式) 这篇主要讲讲jmx方式. 二.启动前设置jmx参数 我这边拿tomcat举例,其余java ...

  2. ELK系列七:Elasticsearch的集群配置和监控以及在部署ELK中踩的坑

    1.基本下载安装 #按照ELK系列一博客安装启动即可,没有大坑,注意一下权限即可 chmod -R 777 ./elasticsearch #此外没有java的,注意安装下JDK,我这次部署的环境是C ...

  3. [工具] Textify – 复制不可能的窗口内容[Win]

    Textify 是一款 Windows 下的小工具,能够复制那些平时无法复制的内容,比如错误提示.菜单按钮文字等等,只需要按下快捷键就可以随意复制,俗称复制不可能. http://rammichael ...

  4. [VS]VS2010如何使用Visual Studio Online在线服务管理团队资源(在线TFS)

    前言 Visual Studio Online,也就是以前的Team Foundation Service,从名字可以看出这是一个团队资源管理服务.在微软的云基础架构中运行,无需安装或配置任何服务器, ...

  5. 理解 ARC 下的循环引用

    本文由 伯乐在线 - nathanw 翻译,dopcn 校稿.未经许可,禁止转载!英文出处:digitalleaves.com.欢迎加入翻译组. ARC 下的循环引用类似于日本的 B 级恐怖片.当你刚 ...

  6. Ios8 Xcode6 设置Launch Image 启动图片

    http://blog.sina.com.cn/s/blog_6c97abf10102voui.html Http://Www.woowen.com/Swift/2014/12/12/Ios8设置La ...

  7. 基础笔记1(进制,浮点,递归,floor,round和ceil)

    1,进制默认是十进制 0开头 8进制 0x     16进制 0b     2进制 2,long 的范围是19位数字.int范围是21亿左右,short 是三万二千左右. 超过int范围的long类型 ...

  8. Unity3D笔记 英保通十 射线碰撞器检测

    射线碰撞检测可以用来检测方向和距离: 通过Physics.RayCast光线投射来实现:常用于射击利用发射的射线来判断.还有对战中刀剑交战中.. 一.要涉及到RayCast和RayCastHit 1. ...

  9. Mac - MySQL初始密码忘记重置MySQL root密码

    在什么情况下,需要重置root密码呢?那就是我们忘记了.还有一种比较坑的,那就是笔者的这种情况.按照正常的情况下,MySQL安装完之后,会弹出一个对话框,显示着一个临时的root密码,但无论笔者如何重 ...

  10. 转利用python实现电影推荐

    “协同过滤”是推荐系统中的常用技术,按照分析维度的不同可实现“基于用户”和“基于产品”的推荐. 以下是利用python实现电影推荐的具体方法,其中数据集源于<集体编程智慧>一书,后续的编程 ...