CaseOf чувствителен к регистру?

Является ли метод indexOf (String) чувствительным к регистру? Если да, то существует ли его регистр, нечувствительный к нему?

Ответ 1

Методы indexOf() чувствительны к регистру. Вы можете сделать их (грубо говоря, сломанным способом, но работая в большом количестве случаев) без учета регистра, предварительно переведя свои строки в верхний/нижний регистр:

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

Ответ 2

Является ли метод 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);
}

Ответ 3

В классе StringUtils библиотеки Apache Commons Lang существует метод игнорирования.

indexOfIgnoreCase (CharSequence str, CharSequence searchStr)

Ответ 4

Да, indexOf чувствителен к регистру.

Самый лучший способ сделать бесчувственность к регистру я нашел:

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

Это сделает регистр нечувствительным indexOf().

Ответ 5

Да, он чувствителен к регистру. Вы можете сделать нечувствительный к регистру indexOf путем преобразования вашего параметра String и String в верхний регистр перед поиском.

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

Вот мое решение, которое не выделяет кучную память, поэтому оно должно быть значительно быстрее, чем большинство других упомянутых здесь реализаций.

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));  
}

Ответ 7

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

Ответ 8

Да, я уверен, что это так. Один из методов работы с использованием стандартной библиотеки:

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

Ответ 9

Я только что посмотрел на источник. Он сравнивает символы, поэтому он чувствителен к регистру.

Ответ 10

Просто подведем итог, 3 решения:

  • с помощью toLowerCase() или toUpperCase
  • с помощью StringUtils apache
  • с использованием регулярного выражения

Теперь, что мне было интересно, кто из них самый быстрый? Я предполагаю в среднем первый.

Ответ 11

Была та же проблема. Я попробовал регулярное выражение и 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 довольно короткий). если у вас есть предложения по улучшению или ошибки, было бы неплохо сообщить мне... (так как я использую этот код в приложении; -)

Ответ 12

Но это не сложно написать:

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());
    }
}

Ответ 13

Что вы делаете с возвращаемым значением индекса?

Если вы используете его для управления своей строкой, не могли бы вы вместо этого использовать регулярное выражение?

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);
    }
}

Ответ 14

Преобразование обеих строк в нижний регистр обычно не является большим делом, но оно будет медленным, если некоторые строки длинны. И если вы сделаете это в цикле, это будет очень плохо. По этой причине я бы рекомендовал indexOfIgnoreCase.

Ответ 15

Первый вопрос уже ответил много раз. Да, методы 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;
}

Ответ 16

indexOf чувствителен к регистру. Это связано с тем, что он использует метод equals для сравнения элементов в списке. То же самое касается и содержит и удаляет.