三点都补得准,尤其「O(1) 前提是手上已有节点」和 tableSizeFor 那处,很多人背了结论不知道边界。不过有两个地方我想再深入讨论一下:
一、removeIf 让「遍历中批量删除」这个LinkedList最后占优的场景也不再成立。 ArrayList 的 removeIf(JDK8+)会先用 BitSet 标记要删的下标,再一次性 compact,System.arraycopy 调用次数从 O(删除数) 降到常数级;LinkedList 的 removeIf 仍是逐节点 unlink,每步还要维护前后指针并改写 expectedModCount。实际压测下,十万级列表删一半,ArrayList 的 removeIf 通常比 LinkedList 快一个数量级。所以严格说,LinkedList 现在还在赢的只剩「Iterator 里散点删、且删得很少」这种窄场景。
二、≤6 这个阈值只在 resize() 拆分容器时生效。 remove 路径调用的是 removeTreeNode,它用的是一个粗略判断:如果根为空,或者根的子树太小,就直接 untreeify,并不拿 size 去和 UNTREEIFY_THRESHOLD 比较。所以「删到 7、6 会退化」这个说法不准确,实际表现是删得差不多时一次性散回链表,而具体时机取决于树形结构。debug 时不要默认「到 6 就退化」去推逻辑。
另外 new HashMap<>(1000) 还有个上限需要注意:tableSizeFor 对超过 1 << 30 的入参直接返回 MAXIMUM_CAPACITY,所以传入特别大的预估容量时不会继续变大。

正式会员
认证极客






