Sonar告警修复:ArrayList的remove()大集合性能热点问题及忽略方案
问题复现
你遇到的告警对应的代码如下:
List<FooListener> listeners = new ArrayList(); public void removeListener(FooListener listener) { listeners.remove(listener); // Sonar严重告警 }
Sonar告警原因是ArrayList.remove(Object)的时间复杂度为O(n),底层需要先遍历全量元素找到匹配下标,删除后还要移动后续所有元素的位置,元素量大时会成为性能瓶颈。
修复方案
根据你的业务场景选择对应方案即可:
- 方案1:替换为
CopyOnWriteArrayList
监听器场景属于典型的读多写少场景(触发监听器的频率远高于注册、移除监听器的频率),直接替换集合实现类即可,无需修改其他业务逻辑,替换后初始化代码为:
该实现类的读写操作都线程安全,符合监听器场景的通用要求。List<FooListener> listeners = new CopyOnWriteArrayList<>(); - 方案2:替换为
Set实现类
如果不需要保证监听器的执行顺序,可以用HashSet;如果需要保序可以用LinkedHashSet,两者的remove方法时间复杂度为O(1),性能远高于ArrayList。注意使用前要确保FooListener类正确重写了equals和hashCode方法。 - 方案3:小数据量场景无需修改
如果你能确定该集合的元素量长期不会超过20个,O(n)的性能损耗可以完全忽略,直接走告警忽略流程即可。
Sonar告警忽略方案
如果确认当前场景不需要优化,可以通过以下方式忽略告警:
- 代码层面直接压制:在对应方法或者代码行上方添加注解
@SuppressWarnings("squid:S2250"),其中squid:S2250是Sonar对应本次性能告警的规则ID,添加后Sonar会自动跳过该位置的规则校验。
提示:添加注解前请再次确认集合体量不会出现大幅增长,避免遗漏真实性能风险。
- 平台层面标记:如果没有代码修改权限,联系公司Sonar管理员为你的账号开通对应项目的问题处理权限,权限开通后即可将告警标记为“误报”或“不会修复”。
内容的提问来源于stack exchange,提问作者Liso
相关产品推荐
相关产品推荐

