indexOf区分大小写?

时间:2009-07-14 15:35:35

标签: java case-sensitive

indexOf(String)方法是否区分大小写?如果是这样,它是否有不区分大小写的版本?

19 个答案:

答案 0 :(得分:63)

indexOf()方法都区分大小写。您可以通过事先将字符串转换为大写/小写来制作它们(粗略地,以一种破碎的方式,但适用于大量情况)不区分大小写:

s1 = s1.toLowerCase(Locale.US);
s2 = s2.toLowerCase(Locale.US);
s1.indexOf(s2);

答案 1 :(得分:39)

  

indexOf(String)方法区分大小写吗?

是的,它区分大小写:

@Test
public void indexOfIsCaseSensitive() {
    assertTrue("Hello World!".indexOf("Hello") != -1);
    assertTrue("Hello World!".indexOf("hello") == -1);
}
  

如果有,是否有不区分大小写的版本?

不,没有。在调用indexOf之前,您可以将两个字符串转换为小写:

@Test
public void caseInsensitiveIndexOf() {
    assertTrue("Hello World!".toLowerCase().indexOf("Hello".toLowerCase()) != -1);
    assertTrue("Hello World!".toLowerCase().indexOf("hello".toLowerCase()) != -1);
}

答案 2 :(得分:17)

Apache Commons Lang库的StringUtils类中有一个忽略大小写方法

indexOfIgnoreCase(CharSequence str,CharSequence searchStr)

答案 3 :(得分:16)

是的,indexOf区分大小写。

我发现不区分大小写的最好方法是:

String original;
int idx = original.toLowerCase().indexOf(someStr.toLowerCase());

这将使用不区分大小写的indexOf()

答案 4 :(得分:11)

这是我的解决方案,它不分配任何堆内存,因此它应该比这里提到的大多数其他实现快得多。

public static int indexOfIgnoreCase(final String haystack,
                                    final String needle) {
    if (needle.isEmpty() || haystack.isEmpty()) {
        // Fallback to legacy behavior.
        return haystack.indexOf(needle);
    }

    for (int i = 0; i < haystack.length(); ++i) {
        // Early out, if possible.
        if (i + needle.length() > haystack.length()) {
            return -1;
        }

        // Attempt to match substring starting at position i of haystack.
        int j = 0;
        int ii = i;
        while (ii < haystack.length() && j < needle.length()) {
            char c = Character.toLowerCase(haystack.charAt(ii));
            char c2 = Character.toLowerCase(needle.charAt(j));
            if (c != c2) {
                break;
            }
            j++;
            ii++;
        }
        // Walked all the way to the end of the needle, return the start
        // position that this was found.
        if (j == needle.length()) {
            return i;
        }
    }

    return -1;
}

以下是验证正确行为的单元测试。

@Test
public void testIndexOfIgnoreCase() {
    assertThat(StringUtils.indexOfIgnoreCase("A", "A"), is(0));
    assertThat(StringUtils.indexOfIgnoreCase("a", "A"), is(0));
    assertThat(StringUtils.indexOfIgnoreCase("A", "a"), is(0));
    assertThat(StringUtils.indexOfIgnoreCase("a", "a"), is(0));

    assertThat(StringUtils.indexOfIgnoreCase("a", "ba"), is(-1));
    assertThat(StringUtils.indexOfIgnoreCase("ba", "a"), is(1));

    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", " Royal Blue"), is(-1));
    assertThat(StringUtils.indexOfIgnoreCase(" Royal Blue", "Royal Blue"), is(1));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "royal"), is(0));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "oyal"), is(1));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "al"), is(3));
    assertThat(StringUtils.indexOfIgnoreCase("", "royal"), is(-1));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", ""), is(0));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "BLUE"), is(6));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "BIGLONGSTRING"), is(-1));
    assertThat(StringUtils.indexOfIgnoreCase("Royal Blue", "Royal Blue LONGSTRING"), is(-1));  
}

答案 5 :(得分:10)

是的,它区分大小写。您可以通过在搜索之前将String和String参数转换为大写来执行不区分大小写的indexOf

String str = "Hello world";
String search = "hello";
str.toUpperCase().indexOf(search.toUpperCase());

请注意,toUpperCase在某些情况下可能无效。例如:

String str = "Feldbergstraße 23, Mainz";
String find = "mainz";
int idxU = str.toUpperCase().indexOf (find.toUpperCase ());
int idxL = str.toLowerCase().indexOf (find.toLowerCase ());

idxU将是20,这是错误的! idxL将是19,这是正确的。导致问题的原因是toUpperCase()将“ß”字符转换为两个字符“SS”,这会抛出索引。

因此,始终坚持使用toLowerCase()

答案 6 :(得分:3)

一旦返回,您对索引值做了什么?

如果您使用它来操纵字符串,那么您可以不使用正则表达式吗?

import static org.junit.Assert.assertEquals;    
import org.junit.Test;

public class StringIndexOfRegexpTest {

    @Test
    public void testNastyIndexOfBasedReplace() {
        final String source = "Hello World";
        final int index = source.toLowerCase().indexOf("hello".toLowerCase());
        final String target = "Hi".concat(source.substring(index
                + "hello".length(), source.length()));
        assertEquals("Hi World", target);
    }

    @Test
    public void testSimpleRegexpBasedReplace() {
        final String source = "Hello World";
        final String target = source.replaceFirst("(?i)hello", "Hi");
        assertEquals("Hi World", target);
    }
}

答案 7 :(得分:2)

我刚刚查看了消息来源。它比较字符,因此区分大小写。

答案 8 :(得分:2)

是的,我很确定。使用标准库解决这个问题的一种方法是:

int index = str.toUpperCase().indexOf("FOO"); 

答案 9 :(得分:2)

总结一下,3个解决方案:

  • 使用toLowerCase()或toUpperCase
  • 使用apache的StringUtils
  • 使用正则表达式

现在,我想知道哪一个是最快的? 我平均猜测第一个。

答案 10 :(得分:2)

有同样的问题。 我尝试了正则表达式和apache StringUtils.indexOfIgnoreCase-Method,但两者都很慢...... 所以我自己写了一个简短的方法......:

public static int indexOfIgnoreCase(final String chkstr, final String searchStr, int i) {
    if (chkstr != null && searchStr != null && i > -1) {
          int serchStrLength = searchStr.length();
          char[] searchCharLc = new char[serchStrLength];
          char[] searchCharUc = new char[serchStrLength];
          searchStr.toUpperCase().getChars(0, serchStrLength, searchCharUc, 0);
          searchStr.toLowerCase().getChars(0, serchStrLength, searchCharLc, 0);
          int j = 0;
          for (int checkStrLength = chkstr.length(); i < checkStrLength; i++) {
                char charAt = chkstr.charAt(i);
                if (charAt == searchCharLc[j] || charAt == searchCharUc[j]) {
                     if (++j == serchStrLength) {
                           return i - j + 1;
                     }
                } else { // faster than: else if (j != 0) {
                         i = i - j;
                         j = 0;
                    }
              }
        }
        return -1;
  }

根据我的测试,它更快......(至少如果你的searchString相当短)。 如果您有任何改进或错误的建议,我很高兴告诉我...(因为我在应用程序中使用此代码; - )

答案 11 :(得分:2)

@Test
public void testIndexofCaseSensitive() {
    TestCase.assertEquals(-1, "abcDef".indexOf("d") );
}

答案 12 :(得分:1)

第一个问题已经多次回答。是的,String.indexOf()方法都区分大小写。

如果您需要区域设置敏感的indexOf(),则可以使用Collator。根据您设置的强度值,您可以进行不区分大小写的比较,并将重音字母视为与非重音字母相同,等等。 以下是如何执行此操作的示例:

private int indexOf(String original, String search) {
    Collator collator = Collator.getInstance();
    collator.setStrength(Collator.PRIMARY);
    for (int i = 0; i <= original.length() - search.length(); i++) {
        if (collator.equals(search, original.substring(i, i + search.length()))) {
            return i;
        }
    }
    return -1;
}

答案 13 :(得分:0)

但写一个并不难:

public class CaseInsensitiveIndexOfTest extends TestCase {
    public void testOne() throws Exception {
        assertEquals(2, caseInsensitiveIndexOf("ABC", "xxabcdef"));
    }

    public static int caseInsensitiveIndexOf(String substring, String string) {
        return string.toLowerCase().indexOf(substring.toLowerCase());
    }
}

答案 14 :(得分:0)

将两个字符串转换为小写字符通常不是什么大问题,但如果某些字符串很长则会很慢。如果你在一个循环中这样做,那将是非常糟糕的。出于这个原因,我建议indexOfIgnoreCase

答案 15 :(得分:0)

 static string Search(string factMessage, string b)
        {

            int index = factMessage.IndexOf(b, StringComparison.CurrentCultureIgnoreCase);
            string line = null;
            int i = index;
            if (i == -1)
            { return "not matched"; }
            else
            {
                while (factMessage[i] != ' ')
                {
                    line = line + factMessage[i];
                    i++;
                }

                return line;
            }

        }

答案 16 :(得分:0)

以下是与Apache的StringUtils版本非常相似的版本:

public int indexOfIgnoreCase(String str, String searchStr) {
    return indexOfIgnoreCase(str, searchStr, 0);
}

public int indexOfIgnoreCase(String str, String searchStr, int fromIndex) {
    // https://stackoverflow.com/questions/14018478/string-contains-ignore-case/14018511
    if(str == null || searchStr == null) return -1;
    if (searchStr.length() == 0) return fromIndex;  // empty string found; use same behavior as Apache StringUtils
    final int endLimit = str.length() - searchStr.length() + 1;
    for (int i = fromIndex; i < endLimit; i++) {
        if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) return i;
    }
    return -1;
}

答案 17 :(得分:0)

我想向ONE提出索赔,并且只有到目前为止有效的解决方案。 :-)

必须解决的三类问题。

  1. 大小写的非传递匹配规则。其他答复中经常提到土耳其语I问题。根据Android源中String.regionMatches的评论,格鲁吉亚比较规则要求在不区分大小写的相等进行比较时将其转换为小写。

  2. 大小写形式的字母数量不同的情况。在这些情况下,到目前为止发布的所有解决方案几乎都失败了。示例:德语STRASSE与Straße的大小写无关,但长度不同。

  3. 重音字符的绑定强度。区域设置和上下文会影响重音是否匹配。在法语中,“é”的大写形式为“ E”,尽管有使用大写重音的趋势。在加拿大法语中,“é”的大写形式毫无例外地是“É”。两个国家/地区的用户在搜索时都希望“ e”与“é”匹配。重音字符和不重音字符是否匹配是特定于语言环境的。现在考虑:“ E”等于“É”吗?是。是的无论如何,在法国语言环境中。

我目前正在使用android.icu.text.StringSearch来正确实现不区分大小写的indexOf操作的先前实现。

非Android用户可以使用com.ibm.icu.text.StringSearch类通过ICU4J软件包访问相同的功能。

请注意在正确的icu程序包(android.icu.textcom.ibm.icu.text)中引用类,因为Android和JRE在其他名称空间(例如Collat​​or)中都具有相同名称的类。

    this.collator = (RuleBasedCollator)Collator.getInstance(locale);
    this.collator.setStrength(Collator.PRIMARY);

    ....

    StringSearch search = new StringSearch(
         pattern,
         new StringCharacterIterator(targetText),
         collator);
    int index = search.first();
    if (index != SearchString.DONE)
    {
        // remember that the match length may NOT equal the pattern length.
        length = search.getMatchLength();
        .... 
    }

测试用例(语言环境,模式,目标文本,expectedResult):

    testMatch(Locale.US,"AbCde","aBcDe",true);
    testMatch(Locale.US,"éèê","EEE",true);

    testMatch(Locale.GERMAN,"STRASSE","Straße",true);
    testMatch(Locale.FRENCH,"éèê","EEE",true);
    testMatch(Locale.FRENCH,"EEE","éèê",true);
    testMatch(Locale.FRENCH,"éèê","ÉÈÊ",true);

    testMatch(new Locale("tr-TR"),"TITLE","tıtle",true);  // Turkish dotless I/i
    testMatch(new Locale("tr-TR"),"TİTLE","title",true);  // Turkish dotted I/i
    testMatch(new Locale("tr-TR"),"TITLE","title",false);  // Dotless-I != dotted i.

PS:尽我所能确定,当根据字典规则,特定于语言环境的规则区分带重音和不带重音的字符时,PRIMARY绑定强度应该做的正确;但我不使用哪种语言环境来测试此前提。捐赠的测试用例将不胜感激。

答案 18 :(得分:-2)

indexOf区分大小写。这是因为它使用equals方法来比较列表中的元素。包含和删除也是如此。