「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战」
前言
- 大数据时代谁掌握了数据,谁就是王者。今天我来分享一个有趣的bug---顽强的数据
业务表现
- 某一天我接了一个需求。要求前端传递一个列表数据然后我根据一定规则进行筛选。将剩余的数据返回至前端
- 这种需求对于我来说还是很得心应手的。立马就开始动起来的,根据条件判断不满足的删除。
- 三下五除二开发完成很自信的上线了。问题也就埋下了
- 随着业务发展之前的筛选开始暴露问题了。之前删除都是删除一个元素没发现问题。后来开始删除多个了。发现有部分数据很顽强删除不了。
扩展
- 在list中remove有两个方法。一个通过索引删除。一个通过对象元素删除;除此之外还有removeAll通过集合删除;removeIf根据条件判断删除。最后在iterator中还有一个remove方法。基本满足我们的各种需求
-
另外我们再来看看如下代码,remove(2) 我们想删除list中2这个元素。但是实际上删除的是list中第三个元素。这就是remove传参的问题。
-
我们只需要将2转换成object就会实现我们的需求
问题定位
-
为了方便演示,下面我通过简化代码来展示。下面是我们实现的删除数据的情况 。 这里也不加条件了就是直接删除数据 。 打印之后你会发现list并不是空
-
是的,你没看错,奇数位的数据都被删除了。但是偶数位的数据顽强的活了下来。下面我们看看remove到底做了啥?
源码分析
-
System.arraycopy这个函数可以会有读者陌生,这个方法是jdk提供的内部会调用C的东西。我们只需要知道这个函数的功能能就行了。他就是将数组从一个位置到另外一个位置的部分复制到新的数组的指定部分。谁白了就是复制。这里的作用就是将后续元素前移。因为ArrayList内部是数组完成的所以需要我们自己处理数据前移 -
当我们循环开始会先删除第一个元素index=0 ; 此时会将数据前移,从而48会被56替换。后面依次如下图
-
两张图片彻底的展示了10个元素的删除过程。偶数位因为数据已经被前移所以躲避了删除的命运。
总结
- 对API的理解不能自以为是,如果想当然的话最终只会自己填坑
- 理解内部原理就不会贻笑大方