博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
清空ArrayList所引发的思考(List相关操作)
阅读量:4053 次
发布时间:2019-05-25

本文共 3200 字,大约阅读时间需要 10 分钟。

清空ArrayList所引发的思考 
ArrayList
list = new ArrayList
();list.add("a111");list.add("b111");list.add("c111");list.add("e111");list.add("f111");list.add("g111");

想办法把list清空,猛一看,这还不简单,so easy ,直接上代码:

for(int i=0;i

执行后才会发现这样写有问题,执行结果:

操作前:[a111, b111, c111, e111, f111, g111]操作后:[b111, e111, g111]

为什么呢?明明看着可以的啊,为什么没有清空啊,问题出在哪呢?

经过一番研究,发现执行循环的时候每次都要调用list.size()方法,由于下面有list.remove(i)操作,所以list.size()是不断变化的,所以会出现上面的情况

 由此想到解决方法:把list.size()赋给一个变量,这样就不会动态变化了,看代码:

int listsize = list.size();for(int i=0;i

心想这样总行了吧,把list.size()专门列出来了,再不行也太难伺候了,执行后才发现还真不行,而且会报错:

操作前:[a111, b111, c111, e111, f111, g111]Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 3, Size: 3	at java.util.ArrayList.RangeCheck(ArrayList.java:547)	at java.util.ArrayList.remove(ArrayList.java:387)	at com.autonavi.test.TestListRemove.main(TestListRemove.java:35)

数组越界异常,哪地方越界了呢,不可能啊,listsize是不变的,每次list.remove(i)怎么会报越界异常呢?

打开源码,一步一步查看,看看到底是在哪一步报错的,经研究才发现:

list是不断变化的,list.remove(i)并不是都是删掉的第一个元素,动态数组跟静态数组最大的区别就是动态数组的存储空间是不断变化的,而静态数组是一成不变的

比方说,循环执行第一次的时候,i=0,list.remove(0),把第一个元素a111删掉了,这时候list只有5个元素了,下标只能是0~4,[b111, c111, e111, f111, g111]

执行第二次的时候,i=1,list.remove(1),把此时list的第二个元素c111删掉了,注意不是删的b111,而是删的c111,这时候list还有4个元素,下标只能是0~3,[b111, e111, f111, g111]

执行第三次的时候,i=2,list.remove(2),把此时list的第三个元素f111删掉了,这时候list还有3个元素,下标只能是0~2,[b111, e111, g111]

for循环执行条件是i<listsize; listsize是刚开始list的size(),值为6,所以还会继续执行下去,这时候就会出现问题了:

执行第四次的时候,i=3,执行list.remove(3)操作,由于当前list只有3个元素,下标只能是0~2,所以执行到这的时候会报越界异常。

 

那到底该怎么办呢?难道一个小小的ArrayList还不能把它清空了,不要急,利用迭代就可以实现:

Iterator
it = list.iterator();for(;it.hasNext();) { it.next(); it.remove();}

注意只有这一种方式才可以在遍历 list的时候执行删除操作,其他方式都不可以实现,会报:ConcurrentModificationException异常

执行结果:

操作前:[a111, b111, c111, e111, f111, g111]操作后:[]

还可以调用list的clear()方法实现清空list,也是最简单的一种形式:

list.clear();

执行结果:

操作前:[a111, b111, c111, e111, f111, g111]操作后:[]

总结:如要是要清空list,用clear()方法,如果是根据条件删除某一个元素,利用迭代实现,里面加个if断判,满足条件的执行it.remove()操作即可

 

1.这样给List赋值是很危险的:

List
notUseChannelList = onUsedChannelList;

因为List是一个对象,这时改变notUseChannelList的值也会改变onUsedChannelList的值,它们指向堆内存中同一块地址
如果有特殊要求,可以像上面那样赋值

一般是利用List的addAll方法,把一个List的值加载到另外一个List中去。

2.这样写是肯定有问题的:

for(Channel channelTemp: notUseChannelList) {    System.out.println("&&&&&&&: " + channelTemp.getChannelId());    for(;it.hasNext();) {     int channelId = it.next().getChannelId();     System.out.println("***it.next().getChannelId()***: " + channelId);     if(channelId == channelTemp.getChannelId()) {      it.remove();     }    }   }

 

因为遍历一遍后it.hasNext()和it.next()的值都改变了,不能再重复了。

应该改成这样:

/**    * 可为当前用户分配的频道    */   List
isUseChannelList = new ArrayList
(); List
notUseChannelList = new ArrayList
(); notUseChannelList.addAll(onUsedChannelList); Iterator
it = channelList.iterator(); for(;it.hasNext();) { int channelId = it.next().getChannelId(); for(Channel channelTemp: notUseChannelList) { if(channelId == channelTemp.getChannelId()) { it.remove(); } } }

主要是记住两点:

1.像下面这样赋值类似于指针操作,一荣俱荣,要想只实现简单的赋值操作用addAll方法。

List
notUseChannelList = onUsedChannelList;

2.it.next()也相当于一个指针,回到末尾后不可能再重新来过了,只有一次机会。

 

 

 

 

 

转载地址:http://iltci.baihongyu.com/

你可能感兴趣的文章
【设计模式】学习笔记13:组合模式(Composite)
查看>>
hdu 1011 Starship Troopers (树形背包dp)
查看>>
hdu 1561 The more, The Better (树形背包dp)
查看>>
【设计模式】学习笔记14:状态模式(State)
查看>>
poj 1976 A Mini Locomotive (dp 二维01背包)
查看>>
Java链式编程(Stream流)
查看>>
系统恢复的,我也不知道什么东西
查看>>
flash 系统字体
查看>>
HDFS Permissions Guide
查看>>
斯坦福大学机器学习——因子分析(Factor analysis)
查看>>
EM及高斯混合模型
查看>>
混合高斯模型算法
查看>>
IntelliJ IDEA 12 + git
查看>>
git-ssh 配置和使用
查看>>
(EM算法)The EM Algorithm
查看>>
Spring配置bean时id和name的相关讨论
查看>>
Spring的depends-on属性Bean依赖
查看>>
匿名内部类实现接口,继承类
查看>>
org.apache.ibatis.builder.IncompleteElementException: Could not find parameter map ***
查看>>
java程序向mysql数据表插入数据时中文乱码问题
查看>>