Java 中跨语言环境的不区分大小写的比较

Ole*_*ksi 5 java localization linguistics

考虑以下 Java 代码比较包含德语字素 \xc3\x9f的小字符串

\n\n
String a = "\xc3\x9f";\nString b = a.toUpperCase();\n\nassertTrue(a.equalsIgnoreCase(b));\n
Run Code Online (Sandbox Code Playgroud)\n\n

比较失败,因为 "\xc3\x9f".toUpperCase() 实际上等于 "SS",最终导致检查失败equalsIgnoreCase()。JavadocstoUpperCase()确实明确提到了这种情况,但是我不明白为什么这不转到 \xe1\xba\x9e,即\xc3\x9f 的大写变体

\n\n

更一般地说,我们应该如何进行不区分大小写的比较,可能跨不同的区域设置。我们应该只使用 或toUpper()之一equalsIgnoreCase(),而不是同时使用两者吗?

\n\n

问题似乎在于 的实现equalsIgnoreCase()包括以下检查:anotherString.value.length == value.length,这似乎与Javadocs for不兼容toUpper(),其中声明:

\n\n
\n

由于大小写映射并不总是 1:1 字符映射,因此生成的字符串可能与原始字符串的长度不同。

\n
\n

Mic*_*nic 6

Java 的Collator类是为不同区域设置敏感的文本比较操作而设计的。由于“大写”的概念在不同区域设置之间有很大差异,因此使用称为比较强度的Collator更细粒度的模型。提供了四个级别,它们如何影响比较取决于区域设置。

\n\n

这是使用Collator德语区域设置进行不区分大小写的字母比较的示例\xc3\x9f的示例:

\n\n
Collator germanCollator = Collator.getInstance(Locale.GERMAN);\nint[] strengths = new int[] {Collator.PRIMARY, Collator.SECONDARY,\n                             Collator.TERTIARY, Collator.IDENTICAL};\n\nString a = "\xc3\x9f";\nString b = "\xc3\x9f".toUpperCase();\n\nfor (int strength : strengths) {\n    germanCollator.setStrength(strength);\n    if (germanCollator.compare(a, b) == 0) {\n        System.out.println(String.format(\n                "%s and %s are equivalent when comparing differences with "\n                + "strength %s using the GERMAN locale.",\n                a, b, String.valueOf(strength)));\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

代码打印出来

\n\n
\n\xc3\x9f 和 SS 在使用德语区域设置与强度 0 进行比较时是等效的。\n\xc3\x9f 和 SS 在使用德语区域设置与强度 1 进行比较时是等效的。\n
\n\n

这意味着德语语言环境认为这两个字符串在PRIMARY和 中相等SECONDARY强度比较方面相等。

\n