【问题标题】:How do I make my string comparison case-insensitive?如何使我的字符串比较不区分大小写?
【发布时间】:2010-02-08 08:50:13
【问题描述】:

我创建了一个 Java 程序来比较两个字符串:

String str = "Hello";

if (str.equals("hello")) {
    System.out.println("match");
} else {
    System.out.println("no match");
}

区分大小写。我怎样才能改变它,使它不是?

【问题讨论】:

  • 如果您知道它区分大小写,则可以在比较之前将其转换为小写或大写。
  • 如果您使用s1.equalsIgnoreCase(s2),您可能无法在需要完成的任何地方执行此操作。我建议您找到字符串的来源——可能是文件或数据库或用户输入——并转换为大写(或小写)并继续使用 .equals 进行比较。
  • 不要转换为小写/大写(如上面 cmets 所建议的那样),使用公认的 equalsIgnoreCase 方法。阅读土耳其语 I 问题和类似的 Unicode 问题以了解基本原理。
  • @OhadSchneider equalsIgnoreCase 无论如何返回土耳其语的错误值,因为它在比较“i”和“I”时返回 true,即使它应该返回 false。所以我怀疑如果你想考虑语言环境,Collator 实际上是要走的路。
  • @OhadSchneider 我想知道。它说按字符执行会产生相同的结果,但是对整个字符串执行 toLowerCase / toUpperCase 并按字符执行也会产生两种不同的结果。

标签: java string comparison case-insensitive


【解决方案1】:

最好的方法是使用str.equalsIgnoreCase("foo")。它专门为此目的进行了优化。

在将它们与equals 进行比较之前,您还可以将两个字符串转换为大写或小写。对于可能没有 equalsIgnoreCase 等效项的其他语言,记住这一技巧很有用。

str.toUpperCase().equals(str2.toUpperCase())

如果您使用的是非罗马字母,请注意 equalsIgnoreCase 的 JavaDoc 的这部分内容

请注意,此方法不考虑语言环境,并且会 导致某些语言环境的结果不理想Collator 类提供区域敏感的比较。

【讨论】:

  • 请注意,这两种解决方案不一定适用于所有语言环境。 String#equalsIgnoreCase 不使用特定于语言环境的大小写规则,而 String#toLowerCase 和 #toUpperCase 使用。
  • @jarnbjo 你能举个例子吗?
  • 至少对土耳其语和德语实施了特定于语言环境的案例规则。土耳其语将带点和不带点的 I 视为两个不同的字母,创建大小写对 iİ 和 ıI,而其他语言将 iI 视为一对,不使用字母 ı 和 İ。在德语中,小写的 ß 大写为“SS”。
【解决方案2】:

【讨论】:

    【解决方案3】:

    String.equalsIgnoreCase 是幼稚的不区分大小写字符串比较最实用的选择。

    但是,需要注意的是,此方法既不进行全大小写折叠也不分解,因此无法执行 Unicode 标准中指定的无大小写匹配。 事实上,JDK API 并不提供对大小写折叠字符数据信息的访问,因此最好将这项工作委托给久经考验的第三方库。

    那个库是ICU,下面是如何实现一个用于不区分大小写的字符串比较的实用程序:

    import com.ibm.icu.text.Normalizer2;
    
    // ...
    
    public static boolean equalsIgnoreCase(CharSequence s, CharSequence t) {
        Normalizer2 normalizer = Normalizer2.getNFKCCasefoldInstance();
        return normalizer.normalize(s).equals(normalizer.normalize(t));
    }
    
        String brook = "flu\u0308ßchen";
        String BROOK = "FLÜSSCHEN";
    
        assert equalsIgnoreCase(brook, BROOK);
    

    在大写或小写字符串上与String.equalsIgnoreCaseString.equals 进行天真比较即使是这个简单的测试也会失败。

    (请注意,尽管预定义的大小写折叠风格 getNFKCCasefoldInstance 与语言环境无关;对于土耳其语言环境,可能需要更多涉及 UCharacter.foldCase 的工作。)

    【讨论】:

      【解决方案4】:

      你必须使用String对象的compareToIgnoreCase方法。

      int compareValue = str1.compareToIgnoreCase(str2);
      

      if (compareValue == 0) 表示str1 等于str2

      【讨论】:

        【解决方案5】:
        import java.lang.String; //contains equalsIgnoreCase()
        /*
        *
        */
        String s1 = "Hello";
        String s2 = "hello";
        
        if (s1.equalsIgnoreCase(s2)) {
        System.out.println("hai");
        } else {
        System.out.println("welcome");
        }
        

        现在它将输出:hai

        【讨论】:

          【解决方案6】:

          在您拥有的默认 Java API 中:

          String.CASE_INSENSITIVE_ORDER
          

          因此,如果您要使用带有排序数据结构的字符串,则无需重写比较器。

          String s = "some text here";
          s.equalsIgnoreCase("Some text here");
          

          您想要在自己的代码中进行纯相等检查。

          只是为了进一步了解有关 Java 中字符串相等性的任何信息。 java.lang.String 类的 hashCode() 函数“区分大小写”:

          public int hashCode() {
              int h = hash;
              if (h == 0 && value.length > 0) {
                  char val[] = value;
          
                  for (int i = 0; i < value.length; i++) {
                      h = 31 * h + val[i];
                  }
                  hash = h;
              }
              return h;
          }
          

          因此,如果您想使用带有字符串作为键的 Hashtable/HashMap,并且“SomeKey”、“SOMEKEY”和“somekey”等键被视为相等,那么您必须将字符串包装在另一个类中(您不能扩展 String,因为它是最终类)。例如:

          private static class HashWrap {
              private final String value;
              private final int hash;
          
              public String get() {
                  return value;
              }
          
              private HashWrap(String value) {
                  this.value = value;
                  String lc = value.toLowerCase();
                  this.hash = lc.hashCode();
              }
          
              @Override
              public boolean equals(Object o) {
                  if (this == o) return true;
                  if (o instanceof HashWrap) {
                      HashWrap that = (HashWrap) o;
                      return value.equalsIgnoreCase(that.value);
                  } else {
                      return false;
                  }
              }
          
              @Override
              public int hashCode() {
                  return this.hash;
              }
          }
          

          然后这样使用它:

          HashMap<HashWrap, Object> map = new HashMap<HashWrap, Object>();
          

          【讨论】:

            【解决方案7】:

            请注意,您可能还想在执行 .equals 或 .equalsIgnoreCase 之前对它们进行空检查。

            空字符串对象不能调用equals方法。

            即:

            public boolean areStringsSame(String str1, String str2)
            {
                if (str1 == null && str2 == null)
                    return true;
                if (str1 == null || str2 == null)
                    return false;
            
                return str1.equalsIgnoreCase(str2);
            }
            

            【讨论】:

            • 注意:后两个语句可以组合产生相同的结果,如下所示:if (str1 == null || str2 == null) return false;.
            • 修改后的代码按照上面的评论更清晰 - 是漫长的一天:)
            • 您也可以将第一行更改为if (str1 == str2) return true;,这既可以处理空值,也可以简化两个字符串引用引用相同字符串对象的情况。
            【解决方案8】:
            【解决方案9】:

            您可以使用equalsIgnoreCase

            【讨论】:

              【解决方案10】:

              关于字符串的更多信息可以在String ClassString Tutorials找到

              【讨论】:

                【解决方案11】:

                为了安全,你可以使用

                org.apache.commons.lang.StringUtils.equalsIgnoreCase(String, String)
                

                org.apache.commons.lang3.StringUtils.equalsIgnoreCase(CharSequence, CharSequence)
                

                【讨论】:

                  【解决方案12】:
                  public boolean newEquals(String str1, String str2)
                  {
                      int len = str1.length();
                  int len1 = str2.length();
                  if(len==len1)
                  {
                      for(int i=0,j=0;i<str1.length();i++,j++)
                      {
                          if(str1.charAt(i)!=str2.charAt(j))
                          return false;
                      }`enter code here`
                  }
                  return true;
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-05-27
                    • 1970-01-01
                    • 2011-01-09
                    相关资源
                    最近更新 更多