字符串驻留可将比较优化至O(1),前提是两字符串已驻留并指向同一内存地址;否则仍为O(n)字符比对,驻留仅对字面量、短标识符等有限字符串自动生效。

字符串驻留能让某些字符串比较快到 O(1),关键不在于“所有比较都变 O(1)”,而在于把原本要逐字符比对的 O(n) 操作,降级为一次指针地址判断——前提是这两个字符串都已驻留且指向同一个内存地址。
驻留前:每次比较都要扫完全部字符
比如有两段文本 "user_status_active" 和 "user_status_active",没驻留时,Python 或 JS 引擎得从头到尾一个字符一个字符核对:第1位 'u' == 'u'?第2位 's' == 's'?……直到最后一位。长度为 n,最坏情况要比较 n 次,时间复杂度就是 O(n)。
驻留后:只比一次内存地址
当这两个字符串都被驻留后,它们实际指向内存中**同一个对象**。此时比较就变成:
id(str1) == id(str2)?
这本质上是一条 CPU 的指针相等指令,不访问字符串内容,不遍历字符,恒定耗时,即 O(1)。
- 这个优化对字典键查找、枚举匹配、状态机跳转等高频场景特别有效
- 但仅对已驻留的字符串生效;动态拼接出来的字符串(如
"user_" + status)默认不驻留,仍走 O(n) 路径 - Python 的
sys.intern()、fast.js 的intern()就是用来主动把这类动态串“拉进”驻留池的
为什么不是所有字符串都自动驻留?
驻留需要维护一个全局哈希表(字符串池),每次创建新串都要查表+可能插入。对超长串或一次性使用的随机串做驻留,反而增加开销、浪费内存。所以语言通常只对:
- 源码里的字面量(如
"OK"、"error") - 符合命名规范的短字符串(如标识符、键名)
- 显式调用
intern()的字符串
做驻留。这是空间与时间的权衡,不是无条件加速。
实测对比很直观
在 Python 中可以验证:
from sys import intern a = "hello" * 1000 b = "hello" * 1000 c = intern(a) d = intern(b) <p>a == b # True,但走 O(n) 字符比对 c is d # True,O(1) 地址比对(因为 c 和 d 是同一对象)
真正获得 O(1) 性能的前提,是两个变量引用的是驻留后的**同一个对象**,而不是语义相同的两个不同对象。


















