在C#中,Grüsse
和Grüße
在大多数情况下都被认为是相同的,正如this精彩网页所解释的那样。我试图在Java中找到类似的行为 - 显然不在java.lang.String
。
我认为java.regex.Pattern
与Pattern.UNICODE_CASE
相结合,我很幸运。 Javadoc说:
UNICODE_CASE启用支持Unicode的案例折叠。当指定此标志时 不区分大小写的匹配,当由CASE_INSENSITIVE标志启用时, 以符合Unicode标准的方式完成。
以下代码:
Pattern p = Pattern.compile(Pattern.quote("Grüsse"),
Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
System.out.println(p.matcher("Grüße").matches());
收益false
。为什么?是否有另一种方法来重现C#案例折叠行为?
----编辑----
正如@VGR指出的那样,String.toUpperCase
会将ß
转换为ss
,这可能是也可能不是案例折叠(也许我在这里混淆概念)。但是,德语区域设置中的其他字符不会“折叠”,例如ü
不会变为UE
。因此,为了使我的初始示例更加完整,有没有办法让Grüße
和Gruesse
在Java中相等?
我认为可以使用java.text.Normalizer
类来做到这一点,但它会将ü
转换为u?
而不是ue
。它也没有提供Locale
的选项,这让我更加困惑。
答案 0 :(得分:1)
使用ICU4J正则表达式,而不是JDK正则表达式: http://userguide.icu-project.org/strings/regexp#TOC-Case-Insensitive-Matching
答案 1 :(得分:1)
使用当前接受的答案:
foo.toUpperCase().equals(bar.toUpperCase())
以下输入不比较相等,即使它们应该:Grüsse
和 GRÜẞE
;或 Grüße
和 GRÜẞE
。
这是为什么?让我们看看大写的字符串:
"Grüsse".toUpperCase(Locale.ROOT) -> "GRÜSSE"
"Grüße".toUpperCase(Locale.ROOT) -> "GRÜSSE"
"GRÜẞE".toUpperCase(Locale.ROOT) -> "GRÜẞE"
如您所见,大写的“尖 S” (ẞ
) 保持原样。要正确处理,请执行以下操作:
foo.toLowerCase(Locale.ROOT).toUpperCase(Locale.ROOT).equals(
bar.toLowerCase(Locale.ROOT).toUpperCase(Locale.ROOT))
注意顺序很重要。如果先大写然后小写,它只会将 ẞ
变成 ß
(小写尖 S)。
答案 2 :(得分:0)
供参考,以下事实:
Character.toUpperCase()
不能作为一个字符进行大小写折叠
必须映射到一个角色。
String.toUpperCase()
会进行大小写折叠。
String.equalsIgnoreCase()
使用Character.toUpperCase()
在内部,所以不进行大小写折叠。
结论(正如@VGR所指出的):如果你需要不区分大小写匹配案例折叠,你需要这样做:
foo.toUpperCase().equals(bar.toUpperCase())
而不是:
foo.equalsIgnoreCase(bar)
关于ü
和ue
的平等,我设法用RuleBasedCollator
和我自己的规则(人们希望Locale.German
建立了这个规则 - 但是,唉)。它看起来非常愚蠢/过度设计,因为我只需要平等,而不是排序/整理,最后我在比较之前找到了一套简单的String.replace
。它很糟糕但它有效且透明/可读。