回顾最初接触的删除元素的方法(在线性表中的删除)
删除方法:就是将要删除的后续元素前移,然后修改数组长度(下面代码是由后面向前遍历(逆遍历)):
package ly.csdn.text; public class Sort1 { private static int size;//原始数组长度 public static void main(String[] args) { //定义一个数组(线性表) int[] arr = {4513,323,2342,24,62,314,53,324}; size = arr.length;//初始化原始数组长度 //删除小于俩百的元素 for(int i=size-1;i>=0;--i) { if(arr[i]<200) { delete(arr,i); --size; } } //输出删除后的序列 for(int i=0;i System.out.print(arr[i] + " "); } } //删除索引为index的元素 private static void delete(int[] arr,int index) { //后续元素前移 for(int i=index;i1;++i) { arr[i] = arr[i+1]; } } }
(这是删除后序列元素)
如果是由前面开始遍历呢?会有预期的结果吗?(以下是错误结果示范)
package ly.csdn.text; public class Sort1 { private static int size;//原始数组长度 public static void main(String[] args) { //定义一个数组(线性表) int[] arr = {4513,323,2342,24,62,314,53,324}; size = arr.length;//原始数组长度初始化 //删除小于俩百的元素 for(int i=0;i if(arr[i]<200) { delete(arr,i); --size; } } //输出删除后的序列 for(int i=0;i System.out.print(arr[i] + " "); } } //删除索引为index的元素 private static void delete(int[] arr,int index) { //后续元素前移 for(int i=index;i1;++i) { arr[i] = arr[i+1]; } } }
查看输出结果,我们发现62没有被删除成功,这是为什么呢?
这是因为删除24后,62被移动到了24这个位置,而 i 仍然在移动所以,错过了访问62的机会,导致没有删除成功。
当然学了集合后,我们清楚可以直接调用方法库直接对元素进行删除(remove(int index)/remove(Object o)),但它真的是最安全,最快捷的删除方法吗?
咱来看看源码它是怎么个实现的吧:
上面那个remove咱不看(只是为了连贯就一起截过来了)咱看看 fastRemove方法。
分析代码:
newsize是定义删除元素后的新长度的(newSize = size - 1和上面线性表所写的 --size 差不多一个含义)
当newSize == i呢就说明删除的元素是最后一个元素,直接退出了判断语句
es[size = newSize] = null 也就是把原先最后一个元素置为空,也就是除去了
它中间调用了System类中的一个方法arraycopy(Object src,int srcPos,Object dest,int destPos,int length)咱看这个方法参数名字也能猜中大概吧:就是把src对象数组索引从dest开始长为length的序列复制到dest索引从destPos的数组中。
这里System.arraycopy(es,i+1,es,i,newSize-i)就是es从i+1开始长为newSize-i(和size-i+1等价,就是索引i后面那段序列)从索引 i 开始复制到es数组(自己本身,自己复制给自己)中去。
对源码分析后发现了啥没?
这不就是和线性表删除结果是一样的,只是它调用了方法库,使用方便了,既然是一样,那么使用它删除多个元素时候就要注意了不可以向前遍历(删除一个的话无所谓,啥方法都一样)。
当我们顺序遍历删除的时候得注意点了,防止出错:
package ly.csdn.text; import java.util. *; public class Sort1 { public static void main(String[] args) { //定义一个数组(线性表) Listlist = new ArrayList<>(); //存入元素 list.add(203); list.add(218); list.add(139); list.add(352); //删除小于俩百的元素 for(int i=0;i if(list.get(i)<200) { list.remove(i); --i;//这里向前挪一位 } } //输出删除后的序列 for(int i=0;i System.out.print(list.get(i) + " "); } }(逆遍历删除是可以的不会出错)
foreach遍历删除呢?
答案是不可以用这个进行删除的。
首先我们得搞清楚foreach遍历元素的时候,是生成iterator,然后用它进行遍历的。
生成iterator,相对应的集合有个参数expectedModcound,这个参数会初始化为在生成iterator前修改该集合的次数,也就是会和List中的Modcound会相同(iterator接口中有检测expectModcound 和 Modcound是否相同的方法,如果不相同会抛出异常)当我们用foreach去遍历,然后用list去删除时,Modcound会随删除而改变,这时候expectModcound与Modcound不相同,那么会抛出异常。
(当我们用foreach删除元素时候会抛出异常, 所以应避免使用它进行该操作)
用线性表删除并不是很简洁。那有没有更好的删除方式呢?
迭代器iterator遍历删除
下面是《阿里巴巴泰山开发手册》上的一个点:
下面是用iterator进行删除的代码:
package ly.csdn.text; import java.util. *; public class Sort1 { public static void main(String[] args) { //定义一个数组(线性表) Listlist = new ArrayList<>(); //存入元素 list.add(203); list.add(218); list.add(139); list.add(120); list.add(352); //删除小于俩百的元素 Iteratorit = list.iterator(); while(it.hasNext()) { Integer x = it.next(); if(x<200) it.remove(); } //输出删除后的序列【203,218,352】 for(int i=0;i System.out.print(list.get(i) + " "); } }用iterator进行删除也要注意:不能同时进行俩次及俩次以上的删除(remove()),这和成员变量cursor(当前遍历的位置)和lastRet(上一次遍历的位置)有关,操作时是对cursor进行操作,操作完cursor会被设值为-1,如果还对它进行操作,那就会抛出数组越界异常,详细看这篇文档有对其的解释(源码分析):Java List用迭代器删除源码细节
其他删除方法
除了上述所写的,我们还可以用List接口中提供的removeAll(Collection> c)方法。
我们可以创建一个集合对象,里面存放要删除的元素,然后再用removeAll方法进行删除即可。
如代码所示:
package ly.csdn.text; import java.util. *; public class Sort1 { public static void main(String[] args) { //定义一个数组(线性表) Listlist = new ArrayList<>(); //存入元素 list.add(203); list.add(218); list.add(139); list.add(120); list.add(352); //删除小于俩百的元素 ListlistDelete = new ArrayList<>(); for(Integer x:list) { if(x<200) listDelete.add(x); } list.removeAll(listDelete); //输出删除后的序列【203,218,352】- 相关阅读:
vscode+makefile开发STM32---支持C++开发
Java中,对象一定在堆中分配吗?
会议OA之待开会议&所有会议
[附源码]Python计算机毕业设计大学生项目众筹系统
Python大数据之linux学习总结——day06_hive02
MATLAB如何将k线图设置为经典红绿配色?
JWT 实现登录认证 + Token 自动续期方案
掌握电子邮件的未来:深入解析IMAP4的革命性特性与实践
保障网络安全:IP代理识别API的作用与应用
一图读懂k8s informer client-go
- 原文地址:https://blog.csdn.net/qq_63691275/article/details/127093374
- 最新文章
沪漂五周年了:我越来越迷茫了
Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
MySQL-Seconds_behind_master的精度误差
[MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
Agent OS :五种驯服不确定性的范式
PortSwigger SQL注入LAB11
数据库即时编译JIT
[Begin]AI Learn Data Day 0
深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU