Java正则的Unicode支持是否包含完整的大小写折叠功能?
Java Unicode正则大小写匹配问题解答
核心结论
Java的正则表达式引擎(java.util.regex.Pattern)以及String类的大小写相关方法,默认仅实现Unicode简单大小写折叠(Simple Case Folding),不支持全大小写折叠(Full Case Folding),这是你遇到匹配失败的根本原因。
问题原因拆解
- 简单大小写折叠是1:1的单字符映射规则,仅处理单个字符之间的大小写对应关系;全大小写折叠支持1:N的多字符映射,比如德语小写字符
ß的全大写折叠对应两个字符SS,拉丁连字符fl的全大写折叠对应两个字符FL,这类多字符映射规则都不在简单折叠的覆盖范围内。 - 你使用的正则模式是
.*(ss).*,开启Pattern.CASE_INSENSITIVE + Pattern.UNICODE_CASE时,引擎只会把模式里的s和单个对应的大写/小写Unicode字符做匹配,不会将ß识别为ss的等价小写形式,因此包含ß的lowerStream匹配失败,而直接包含SS的upperStream匹配成功。 - Ruby等其他语言的正则引擎默认采用全大小写折叠规则,因此可以正确匹配
ß和SS的等价关系,和Java的表现产生差异。 String.equalsIgnoreCase()、无指定Locale的toLowerCase()/toUpperCase()方法同样基于简单大小写折叠实现,且大小写转换还受系统默认Locale影响:只有指定德语Locale调用toUpperCase(Locale.GERMAN)时,才会将ß转换为SS,默认Locale下ß的大写转换结果通常是大写ẞ字符,自然无法和SS完成等值比较。
关于官方文档的说明
早期JDK版本的Pattern类文档确实没有明确标注采用简单大小写折叠,仅说明UNICODE_CASE会遵循Unicode标准完成大小写不敏感匹配。从JDK 9开始,官方文档已经补充了相关说明,明确其大小写匹配采用的是Unicode简单大小写折叠规则,不处理多字符的折叠映射。
内容的提问来源于stack exchange,提问作者Hoobajoob
相关产品推荐
相关产品推荐

