如何比较原始类型中的字符忽略大小写

我正在写这些代码行:

String name1 = fname.getText().toString(); String name2 = sname.getText().toString(); aru = 0; count1 = name1.length(); count2 = name2.length(); for (i = 0; i < count1; i++) { for (j = 0; j < count2; j++) { if (name1.charAt(i)==name2.charAt(j)) aru++; } if(aru!=0) aru++; } 

我想比较两个StringCharacter s忽略这个案例。 仅使用IgnoreCase不起作用。 添加’ ASCII值也不起作用。 我该怎么做呢?

Java API的Character类具有您可以使用的各种function。

您可以将两侧的char转换为小写:

 Character.toLowerCase(name1.charAt(i)) == Character.toLowerCase(name2.charAt(j)) 

还有一种方法可用于validation字母是大写还是小写:

 Character.isUpperCase('P') Character.isLowerCase('P') 

使用toLowerCase无论是在字符串上还是在字符中,都无法完全正确地完成工作。 问题是大写或小写都有变体字形,并且取决于你是否大写或小写你的字形可能会或可能不会被保留。 当你说小写字形的两个变体被比较忽略的情况时,你甚至不清楚你的意思 :它们是不是相同? (请注意,还有混合大小写字形: \u01c5, \u01c8, \u01cb, \u01f2或Dž,Lj,Nj,Dz,但这里建议的任何方法都适用于那些,只要它们应该算作相同的完全上部或完全小写的变体。)

使用Char还有一个问题:大约80个代码点不能用单个Char表示,它们是大/小写变体(每个40个),至少由Java的代码点上/下shell检测到。 因此,您需要获取代码点并更改这些代码。

但是代码点对变体字形没有帮助。

无论如何,这里有一个由于变体而有问题的字形的完整列表,显示它们如何对抗6种变体方法:

  1. 字符toLowerCase
  2. 字符toUpperCase
  3. 字符串toLowerCase
  4. 字符串toUpperCase
  5. String equalsIgnoreCase
  6. 字符toLowerCase(toUpperCase) (反之亦然)

对于这些方法, S表示变体的处理方式彼此相同, D表示变体被视为彼此不同。

 Behavior Unicode Glyphs =========== ================================== ========= 1 2 3 4 5 6 Upper Lower Var Up Var Lo Vr Lo2 UL ul l2 - - - - - - ------ ------ ------ ------ ------ - - - - - DDDDSS \u0049 \u0069 \u0130 \u0131 I i İ ı SDSDSS \u004b \u006b \u212a K k K DSDSSS \u0053 \u0073 \u017f S s ſ DSDSSS \u039c \u03bc \u00b5 Μ μ µ SDSDSS \u00c5 \u00e5 \u212b Å å Å DSDSSS \u0399 \u03b9 \u0345 \u1fbe Ι ι ͅ ι DSDSSS \u0392 \u03b2 \u03d0 Β β ϐ DSDSSS \u0395 \u03b5 \u03f5 Ε ε ϵ DDDDSS \u0398 \u03b8 \u03f4 \u03d1 Θ θ ϴ ϑ DSDSSS \u039a \u03ba \u03f0 Κ κ ϰ DSDSSS \u03a0 \u03c0 \u03d6 Π π ϖ DSDSSS \u03a1 \u03c1 \u03f1 Ρ ρ ϱ DSDSSS \u03a3 \u03c3 \u03c2 Σ σ ς DSDSSS \u03a6 \u03c6 \u03d5 Φ φ ϕ SDSDSS \u03a9 \u03c9 \u2126 Ω ω Ω DSDSSS \u1e60 \u1e61 \u1e9b Ṡ ṡ ẛ 

进一步复杂化的是,除非你知道你是土耳其语,否则没有办法让土耳其语我是正确的(即点缀版本与未发布的版本不同)。 除非你知道语言环境(即非土耳其语: iI是同一个忽略的情况;土耳其语,不是),否则这些方法都不会给出正确的行为。

总的来说,使用toUpperCase可以得到最接近的近似值,因为您只有五个大写变体(或四个,不包括土耳其语)。

您还可以尝试专门拦截这五个麻烦的案例,并单独调用toUpperCase(toLowerCase(c)) 。 如果你仔细选择你的警卫(如果c < 0x130 || c > 0x212B只是toUpperCase ,那么通过其他选择)你可以获得低范围内的字符只有约20%的速度惩罚(相比之下,你可以获得约4倍的速度惩罚)将单个字符转换为字符串并将equalsIgnoreCase转换为它们,如果您在危险区域中有很多,则只会大约2 equalsIgnoreCase惩罚。 你仍然有点缀I的区域设置问题,但否则你的状态不错。 当然,如果你可以在更大的字符串上使用equalsIgnoreCase ,那么你最好这样做。

以下是完成工作的示例Scala代码:

 def elevateCase(c: Char): Char = { if (c < 0x130 || c > 0x212B) Character.toUpperCase(c) else if (c == 0x130 || c == 0x3F4 || c == 0x2126 || c >= 0x212A) Character.toUpperCase(Character.toLowerCase(c)) else Character.toUpperCase(c) } 

您可以在使用之前更改String的大小写,如下所示

 String name1 = fname.getText().toString().toLowerCase(); String name2 = sname.getText().toString().toLowerCase(); 

然后继续rest操作。

您可以将两个字符放在小写字母中然后进行比较。

在比较字符/ lowercasing / uppercasing时,你必须考虑土耳其语问题:

我建议转换为String并使用带有不变文化的toLowerCase(至少在大多数情况下)。

public final static Locale InvariantLocale = new Locale(Empty,Empty,Empty); str.toLowerCase(InvariantLocale)

查看类似的C# string.ToLower()和string.ToLowerInvariant()

注意:不要使用String.equalsIgnoreCase http://nikolajlindberg.blogspot.co.il/2008/03/beware-of-java-comparing-turkish.html

使用忽略大小写比较2个字符串之间位置的char的通用方法。

 public static boolean isEqualIngoreCase(char one, char two){ return Character.toLowerCase(one)==Character .toLowerCase(two); } public static boolean isEqualStringCharIgnoreCase(String one, String two, int position){ char oneChar = one.charAt(position); char twoChar = two.charAt(position); return isEqualIngoreCase(oneChar, twoChar); } 

函数调用

 boolean isFirstCharEqual = isEqualStringCharIgnoreCase("abc", "ABC", 0) 

JDK就是这样做的(改编自OpenJDK 8, String.java / regionMatches ):

 static boolean charactersEqualIgnoringCase(char c1, char c2) { if (c1 == c2) return true; // If characters don't match but case may be ignored, // try converting both characters to uppercase. char u1 = Character.toUpperCase(c1); char u2 = Character.toUpperCase(c2); if (u1 == u2) return true; // Unfortunately, conversion to uppercase does not work properly // for the Georgian alphabet, which has strange rules about case // conversion. So we need to make one last check before // exiting. return Character.toLowerCase(u1) == Character.toLowerCase(u2); } 

我想这对土耳其人也有效吗?