是否存在字符串使equalsIgnoreCase与Locale.US下toLowerCase比较结果不一致?
大小写不敏感字符串比较与toLowerCase转换后比较的结果差异问题
我正在尝试回应同事提出的一个假设性疑问:关于大小写不敏感字符串比较与使用toLowerCase转换后比较的结果差异问题。
开发中我们会尽可能使用equalsIgnoreCase(或对应语言/环境原生提供的大小写不敏感比较方法)实现字符串比较,但在部分场景下需要计算字符串哈希值后通过哈希比对相等性。为了避免无法通过土耳其测试(Turkey Test),我们采用hash(s.toLowerCase(Locale.US))的方式计算哈希,但仍存在顾虑:是否存在某对字符串满足以下表达式:
s1.equalsIgnoreCase(s2) != (s1.toLowerCase(Locale.US) == s2.toLowerCase(Locale.US))
即原生大小写不敏感比较的结果,与指定US区域设置转小写后比较的结果不一致。如果存在这样的字符串对,那么通过sha(s.toLowerCase(Locale.US))生成哈希做比对时,就可能出现实际相等的字符串被误判为不相等的问题。
是否存在满足上述表达式的字符串对(s1, s2)?
后续编辑:因采纳了评论区提供的关联答案,故不再单独发布自问自答内容。
确实存在这样的字符串对,典型案例为("ϑ", "ϴ")(希腊字母Theta、Small Theta):二者通过equalsIgnoreCase判定为相等,但调用.toLowerCase(Locale.US)时两个字符都不会被转换,因此转小写后比较结果为不相等,属于已知边界场景。
对应的Scala验证代码如下:
import java.util.Locale def lower(s: String) = s.toLowerCase(Locale.US) def upper(s: String) = s.toUpperCase(Locale.US) val s1 = "ϑ" val s2 = "ϴ" println(s"CI Equals: ${s1 equalsIgnoreCase s2}") // true println(s"Lower Equals: ${lower(s1) == lower(s2)}") // false println(s"UpperLower Equals: ${lower(upper(s1)) == lower(upper(s2))}") // true
关联答案的结论:
真正的大小写不敏感比较必须校验字符串转大写后再转小写的结果是否相等。
内容的提问来源于stack exchange,提问作者Dylan
相关产品推荐
相关产品推荐

