ArrayList在中间增删场景最不靠谱,因需数组整体拷贝;LinkedList虽理论O(1)但缓存命中率低,实际更慢;高频增删应选ArrayDeque或数据库B+树。

ArrayList 和 LinkedList 在高频增删场景下谁更不靠谱
别看 ArrayList 默认被 IDE 自动补全,它在尾部追加确实快,但只要业务逻辑里出现「中间插入」或「按索引频繁删除」,ArrayList 就会触发数组整体拷贝——比如日志归档模块中按时间戳插入事件,每插一次平均移动 N/2 个元素。而 LinkedList 虽然理论上插入 O(1),但它的节点分散在堆内存各处,CPU 缓存命中率极低,实际吞吐反而比 ArrayList 还差 30%~50%。真要中间增删,优先考虑 ArrayDeque(非并发)或把数据结构下沉到数据库层用 B+ 树索引。
ConcurrentHashMap 为什么不能直接替代 HashMap 做本地缓存
ConcurrentHashMap 的分段锁或 CAS 操作带来可观的线程安全开销,如果业务是单线程初始化 + 多线程只读(比如配置加载后全局共享),用 HashMap 配合 Collections.unmodifiableMap() 更轻量;若读多写少且需实时更新,ConcurrentHashMap 合理,但要注意 computeIfAbsent() 的 lambda 里别做 I/O 或长耗时操作,否则会卡住整个 segment。另外,它不保证遍历一致性——迭代过程中其他线程修改,你既不会抛 ConcurrentModificationException,也看不到新值,这点常被忽略。
Set 实现选错导致去重失效的典型现场
很多团队用 HashSet 存 DTO 对象去重,结果发现重复数据没滤掉。根本原因是没重写 equals() 和 hashCode(),或者只重写了 equals() 忘了 hashCode()。更隐蔽的是用了 Lombok 的 @Data 却在字段上加了 @EqualsAndHashCode.Exclude,导致关键业务字段被排除。如果对象天然有序、且需范围查询(比如查“创建时间在 7 天内的订单 ID”),TreeSet 看似合理,但它要求 Comparable 实现必须严格一致——一旦比较逻辑和业务语义错位(如把 null 当最小值但数据库允许 null 在中间),排序和查找都会出错。
业务参数校验时用 Arrays.asList() 包装数组的坑
Arrays.asList() 返回的是 Arrays$ArrayList,它不是 java.util.ArrayList,不支持 add()、remove()、clear(),调用直接抛 UnsupportedOperationException。常见于 Spring Controller 层接收数组参数后想转成 List 做校验,结果在后续流程里动态添加错误信息时报错。正确做法是显式 new:new ArrayList(Arrays.asList(arr)),或者 JDK 10+ 直接用 List.copyOf(Arrays.asList(arr))(注意它是不可变的)。另外,如果原始数组是基本类型(int[]),Arrays.asList(intArr) 会把整个数组当一个元素塞进去,必须先 boxed 成 Integer[]。
Collection 接口选型从来不是背 API 文档能解决的,关键得看清业务访问模式:是随机读多,还是顺序遍历多?是否跨线程共享?修改频次和位置在哪里?有没有隐式排序需求?这些比“哪个更快”重要得多。

















