由一个bug引起的关于list的思考

今天QA提了一个bug,说是在某些情况下,该显示4个标签的时候却出现了5个标签,某些情况下又是正确的,很奇怪,让我调查一下。翻看了一下代码,发现以下一段代码
这里写图片描述
肯定是这段代码的问题了,刚开始比较蒙圈,以为是++i的原因,但是后来验证了一下,并不是这个原因,在for循环里,i++和++i最终效果都是一样的,那么,问题到底在哪里?

问题出在哪里

这段代码的意思很明显,就是在size>4 的时候,删除掉 下标4,5,6…….所对应的值,只剩下0-3,所以刚开始我就被绕进去了,感觉代码没啥问题,但是出现了这个bug肯定是不对的。
问题出现在哪里呢?出现在list的大小里面。
代码在循环里对list进行了操作,remove掉了当前下标下的值,但是在循环第二遍的时候又重新去获取list的大小了,这时候list的大小肯定是减少了1的,也就达不到原先预想的效果。比如,原来有6个数据,限制数据数量为4,当循环体里将下标4删除,然后按照预想的去删除下标5 的时候,重新获取了一下size的大小,此时就是5 了,而i的值也增加到了5,这样就进不去循环体了,直接跳出来了。
这个代码估计存在好几个版本了,之前没发现可能是后台就没有下发过超过4个的,或者是最多下发了5个数据吧~

解决方案

既然问题找到了,那么解决方案就出来了,因为在for循环里重复取值的原因,导致本来应该循环两遍的,因为数据减少,只循环了一次,所以解决方案就是
这里写图片描述
定义一个变量totalCount,先取值,然后再遍历删除,这样就不会重复取值了,但是结果很明显,肯定会数组越界,因为下标一直在增加,还是按照之前的size大小来的,但是明显size已经减少了,再去remove就会产生越界。
可是为什么会习惯性这么写呢?
上面说的很清楚了,size的大小在重复取值~,这点数据量小没多大事情,但是数据量大就会产生性能问题,所以,以后写代码,不要在循环里重复取size大小。。。。

那么到底解决方案有哪些呢?暂时想到的两个最直接的方案就是
1.倒叙删除
这里写图片描述
不是4-5-6这么删除,而是6-5-4这么删除,这样就不会有数组越界问题了~
2,sublist函数
这里写图片描述
这个是比较官方的一种做法,也是正确的,但是我们项目里是需要arrayList类型的,这么做不行,那就强转一下吧。
这里写图片描述
结果报错了~
这里写图片描述
很奇怪,怎么强转出错了,我记得List是可以强转为ArrayList的呀。
不服气,写代码尝试了一下
这里写图片描述
正确的,也没出错。
那么问题到底出在哪里呢?
在sublist函数里
subList函数会返回一个List对象,而该list对象没有指向任何子对象。

父类强转子类

关于父类能否强转子类,网上众说纷纭,有的说能,有的说不能。到底能不能,看自己理解吧 。
之所以
这里写图片描述
这段代码没有报错,是因为我们在创建list1对象的时候,我们将list1对象已经指向arrylist这个子类的,已经表明我就是一个arraylist,只不过用一个父类去引用了而已,但是sublist创建出来的父对象,我并不知道你具体指的哪个子类,因为我的子类太多了,你啥都不干直接强转,肯定出错,这就好比 它原来是一只动物,你没说它是什么动物就强行转换成一只狗可以么?不可以!
但是 如果 它原来就是一只狗的话
Animal animal = new Dog();
Dog dog2 = (Dog)animal;
这样就不会报错了。
大概就是这么一个理吧。

逆向思维

啰嗦了这么多,其实,一开始我们就把问题复杂化了,如果要是限制4个,我们在源头就该去判断数量,如果>4直接限制4个就好了,而不是全部添加进去之后再去删除~没必要~

参考
http://blog.csdn.net/chenssy/article/details/44102915
http://bbs.csdn.net/topics/360056842
http://blog.csdn.net/ld422586546/article/details/9707997

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值