java 如何在list中删除我指定的对象

网友投稿 285 2022-09-14


java 如何在list中删除我指定的对象

目录遍历list,删除指定对象的三种方式1、再定义一个List,用来保存需要删除的对象2、不用for-each循环,使用倒序循环删除3、用迭代器删除Iterator的工作机制List集合删除元素的正确姿势常用的错误方式有以下三种

遍历list,删除指定对象的三种方式

1、再定义一个List,用来保存需要删除的对象

修改部分代码:

List userRemove = new ArrayList();

//找出要删除的用户

System.err.println("要删除的用户:");

for (User result : list)

{

if (result.getId() == 1 || result.getId() == 3)

{

userRemove.add(result);

System.err.println("id:" + result.getId() + "\tname:" + result.getName());

}

}

list.removeAll(userRemove);

//剩下的用户

System.err.println("剩下的用户:");

for (User result : list)

{

System.err.println("id:" + result.getId() + "\tname:" + result.getName());

}

2、不用for-each循环,使用倒序循环删除

for(int i=list.size()-1;i>=0;i--)

{

User result = list.get(i);

if (result.getId() == 3)

{

list.remove(result);

System.err.println("id: " + result.getId() + "\tname: " + result.getName());

}

}

3、用迭代器删除

Iterator it = list.iterator();

while (it.hasNext())

{

User userObj = it.next();

if (userObj.getId() == 3)

{

it.remove();

}

}

//剩下的用户

System.err.println("剩下的用户:");

for (User result : list)

{

System.err.println("id:" + result.getId() + "\tname:" + result.getName());

}

PS: 用for-each遍历 实际上使用的是Iterator迭代器

Iterator的工作机制

Iterator是工作在一个独立的线程中,并且拥有一个 mutex锁,就是说Iterator在工作的时候,是不允许被迭代的对象被改变的。

Iterator被创建的时候,建立了一个内存索引表(单链表),这 个索引表指向原来的对象,当原来的对象数量改变的时候,这个索引表的内容没有同步改变,所以当索引指针往下移动的时候,便找不到要迭代的对象,于是产生错 误。

List、Set等是动态的,可变对象数量的数据结构,但是Iterator则是单向不可变,只能顺序读取,不能逆序操作的数据结构,当 Iterator指向的原始数据发生变化时,Iterator自己就迷失了方向。

三种方式 方便以后学习 !

List集合删除元素的正确姿势

在阅读阿里巴巴规约的时候发现有一条规约是关于List的【不要在foreach里面进行元素的remove/add操作,remove请使用Iterator方式】。然后想起以前自己做项目的时候删除某一元素的逻辑报下标越界错误,那时候记得处理是用一新的List进行存储,然后整体从原List移除所有符合规则的元素,现在做一总结。用这个Iterator主要可以避免下标越界或者遍历是漏掉符合规则的下一个数据。

先拉出来正确删除元素的姿势。正确姿势是利用Iterator的remove方法。具体操作如下:

public static void main(String[] args) {

List lists = new ArrayList();

lists.add(1);

lists.add(2);

lists.add(3);

lists.add(4);

lists.add(5);

Iterator iterator = lists.iterator();

while (iterator.hasNext()){

Integer obj = iterator.next();

if(3==obj || 4==obj){

iterator.remove();

}

}

System.out.println(lists);

}

附上自己比较笨的操作方式:

public static void main(String[] args){

List lists = new ArrayList();

List listscopy = new ArrayList<>();

lists.add(1);

lists.add(2);

lists.add(3);

lists.add(4);

lists.add(5);

int size = lists.size();

for (int i = 0; i < lists.size(); i++) {

if(3==lists.get(i) || 4 == lists.get(i)){

listscopy.add(lists.get(i));

}

}

lists.removeAll(listscopy);

System.out.println(lists);

}

常用的错误方式有以下三种

第一种方式,多出现下标越界问题。这个主要原因是因为我们在循环遍历时,将我们的长度进行定值确定。而忽略掉在满足条件时,list的长度是减少的。

public static void main(String[] args) {

List lists = new ArrayList();

lists.add(1);

lists.add(2);

lists.add(3);

lists.add(4);

lists.add(5);

int size = lists.size(); // 定长设置,会造成元素下标越界,如果将for中变量直接换成lists.size()可以吗?

SiBzCPBjb for (int i = 0; i < size; i++) {

if(3==lists.get(i) || 4 == lists.get(i)){

lists.remove(i); //lists.remove(lists.get(i));

}

}

System.out.println(lists);

}

第二种方式也就是上面的注释所说,既然会出现下标越界,那我就利用动态的大小不就可以了,但是利用这种方法会产生另外一种情况,就是会忽略掉remove元素后面的一个元素,这个是因为删除符合规则的元素后,list长度减一,而同时后面的元素往前补一位,造成当前i值下对应两个元素。

public static void main(String[] args) {

List lists = new ArrayList();

lists.add(1);

lists.add(2);

lists.add(3);

lists.add(4);

lists.add(5);

int size = lists.size();

for (int i = 0; i < lists.size(); i++) {

if(3==lists.get(i) || 4 == lists.get(i)){

lists.remove(i); //lists.remove(lists.get(i));

}

}

System.out.println(lists); // 打印[1, 2, 4, 5] 此时会将4忽略掉

}

第三种方式是利用增强FOR循环造成的。这种方式会直接给报错:

ERRORInfo:

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)

public static void main(String[] args) {

List lists = new ArrayList();

lists.add(1);

lists.add(2);

lists.add(3);

lists.add(4);

lists.add(5);

for (Integer i : lists){

if(3==i || 4==i){

lists.remove(i);

}

}

System.out.println(lists);

}

这种情况下。主要是集合遍历是使用Iterator, Iterator是工作在一个独立的线程中,并且拥有一个互斥锁。Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast原则 Iterator 会马上抛出java.util.Concurrehttp://ntModificationException 异常。所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:网络管理员&MCSE2003之12:第7章 使用组策略管理用户环境(下)
下一篇:计算机软件技术的三大流派(常用的两大流派计算机)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~