contains 仅做子串搜索,不区分位置;前缀匹配应使用 startswith 系列方法,注意大小写处理、性能优势及正则适用场景。

contains 不能用于前缀判断,别被名字误导
很多开发者看到 contains 就默认它能查“开头有没有”,结果在 Java、C# 或某些 JS 库里踩坑——contains 只做子串搜索,不区分位置。比如 "banana".contains("na") 返回 true,但它根本不管这个 "na" 是在开头、中间还是结尾。
真正做前缀匹配,得用明确标识“开头”的方法:
- Java:用
String.startsWith(),不是contains() - JavaScript:用
String.prototype.startsWith()(ES6+),或str.indexOf("prefix") === 0 - C#:用
string.StartsWith(),注意它默认区分大小写 - Python:用
str.startswith(),支持元组参数批量匹配多个前缀
startsWith 的大小写处理必须显式指定
多数语言的 startsWith 默认严格区分大小写,这在处理用户输入或 HTTP Header 等场景下容易漏判。比如 "Content-Type".startsWith("content") 在 Java/JS/C# 中都返回 false。
解决方式因语言而异:
- Java:传入
String.CASE_INSENSITIVE_ORDER比较器,或先转小写再比(注意toLowerCase()的区域敏感问题) - JavaScript:没有内置忽略大小写的选项,常用
str.toLowerCase().startsWith(prefix.toLowerCase()) - C#:用
StringComparison.OrdinalIgnoreCase作为第二个参数 - Python:不支持直接忽略大小写,需手动转换或用正则
re.match(r"^prefix", s, re.I)
性能差异:startsWith 比 substring + equals 快得多
有人图省事写 str.substring(0, prefix.length()).equals(prefix),这在 Java 里不仅可读性差,还可能抛 StringIndexOutOfBoundsException(当 str 比 prefix 短时)。而 startsWith 内部做了长度预检,安全且高效——它逐字符比较,一旦发现不匹配就立即返回,不会创建新字符串对象。
实测(Java 17,100 万次调用):
-
str.startsWith(prefix):约 8ms -
str.substring(0, n).equals(prefix):约 25ms,且有异常风险
正则不是首选,除非你要动态前缀或复杂模式
用 ^abc 做前缀匹配当然可行,但引入正则就有额外开销和学习成本。对固定前缀,startsWith 更轻量、更易读、更难出错。
只在以下情况考虑正则:
- 前缀本身是变量且含特殊字符(如
"a.b"要按字面匹配,得转义后构造正则) - 需要同时满足前缀 + 后续格式约束(如
"v\d+\.\d+\.\d+") - 运行时拼接多段条件,逻辑远超简单“开头是…”
否则,老老实实用 startsWith——它就是为这事设计的,别绕路。










