¿Índice de Mayúsculas y Minúsculas?


¿El método indexOf(String) distingue entre mayúsculas y minúsculas? Si es así, ¿hay una versión insensible a mayúsculas y minúsculas?

Author: Brian, 2009-07-14

16 answers

Los métodos indexOf() distinguen entre mayúsculas y minúsculas. Puedes hacerlas (aproximadamente, de una manera rota, pero trabajando para muchos casos) insensibles a mayúsculas y minúsculas convirtiendo tus cadenas a mayúsculas/minúsculas de antemano:

s1 = s1.toLowerCase(Locale.US);
s2 = s2.toLowerCase(Locale.US);
s1.indexOf(s2);
 58
Author: Joey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-06 17:42:23

¿El método indexOf(Cadena) distingue entre mayúsculas y minúsculas?

Sí, distingue entre mayúsculas y minúsculas:

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

Si es así, ¿hay una versión insensible a mayúsculas y minúsculas?

No, no lo hay. Puede convertir ambas cadenas a minúsculas antes de llamar a indexOf:

@Test
public void caseInsensitiveIndexOf() {
    assertTrue("Hello World!".toLowerCase().indexOf("Hello".toLowerCase()) != -1);
    assertTrue("Hello World!".toLowerCase().indexOf("hello".toLowerCase()) != -1);
}
 39
Author: dfa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-14 15:48:30

Hay un método ignore case en la clase StringUtils de Apache Commons Lang library

IndexOfIgnoreCase (CharSequence str, CharSequence searchStr)

 17
Author: deepika,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-29 09:14:53

Sí, indexOf distingue entre mayúsculas y minúsculas.

La mejor manera de hacer insensibilidad a mayúsculas y minúsculas que he encontrado es:

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

Que hará un caso insensible indexOf().

 15
Author: jjnguy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-14 02:13:50

Aquí está mi solución que no asigna ninguna memoria de montón, por lo tanto, debería ser significativamente más rápido que la mayoría de las otras implementaciones mencionadas aquí.

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

Y aquí están las pruebas unitarias que verifican el comportamiento correcto.

@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));  
}
 11
Author: Zach Vorhies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-22 21:51:46

Sí, distingue entre mayúsculas y minúsculas. Puede hacer un indexOf que no distingue entre mayúsculas y minúsculas convirtiendo su cadena y el parámetro String en mayúsculas antes de buscar.

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

Tenga en cuenta que toUpperCase puede no funcionar en algunas circunstancias. Por ejemplo esto:

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

IdxU tendrá 20, ¡lo cual está mal! idxL será 19, lo cual es correcto. Lo que está causando el problema es que tha toUpperCase () convierte el carácter "ß" en DOS caracteres, "SS" y esto arroja el índice.

En consecuencia, siempre apégate a toLowerCase()

 10
Author: Nick Lewis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-07 13:39:15

¿Qué está haciendo con el valor del índice una vez devuelto?

Si lo está usando para manipular su cadena, entonces ¿podría no usar una expresión regular en su lugar?

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);
    }
}
 3
Author: toolkit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-14 23:25:10

Acabo de mirar la fuente. Compara caracteres por lo que distingue entre mayúsculas y minúsculas.

 2
Author: John Topley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-14 15:41:51
@Test
public void testIndexofCaseSensitive() {
    TestCase.assertEquals(-1, "abcDef".indexOf("d") );
}
 2
Author: Paul McKenzie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-14 15:49:52

Sí, estoy bastante seguro de que lo es. Un método de trabajo alrededor de que el uso de la biblioteca estándar sería:

int index = str.toUpperCase().indexOf("FOO"); 
 2
Author: Yacoby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-14 16:04:34

Tenía el mismo problema. Probé la expresión regular y el apache StringUtils.indexOfIgnoreCase-Método, pero ambos eran bastante lentos... Así que yo mismo escribí un método corto...:

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

Según mis pruebas es mucho más rápido... (al menos si tu cadena de búsqueda es bastante corta). si tiene alguna sugerencia de mejora o errores, sería bueno que me lo haga saber... (ya que uso este código en una aplicación ;-)

 2
Author: phil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-02 15:16:26

Solo para resumirlo, 3 soluciones:

  • usando toLowerCase () o toUpperCase
  • usando StringUtils de apache
  • usando expresiones regulares

Ahora, lo que me preguntaba era ¿cuál es el más rápido? Supongo que en promedio el primero.

 2
Author: max,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-02 18:28:05

La primera pregunta ya ha sido contestada muchas veces. Sí, todos los métodos String.indexOf() distinguen entre mayúsculas y minúsculas.

Si necesita un indexOf() sensible a la configuración regional, puede usar el Collator . Dependiendo del valor de fuerza que establezca, puede obtener una comparación insensible a mayúsculas y minúsculas, y también tratar las letras acentuadas como las no acentuadas, etc. Aquí hay un ejemplo de cómo hacer esto:

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;
}
 1
Author: Bernd S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-14 01:31:58

Pero no es difícil escribir uno:

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());
    }
}
 0
Author: Carl Manaster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-14 17:32:13

Convertir ambas cadenas a minúsculas no suele ser un gran problema, pero sería lento si algunas de las cadenas son largas. Y si haces esto en un bucle, entonces sería realmente malo. Por esta razón, yo recomendaría indexOfIgnoreCase.

 0
Author: Jakub Vrána,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-11 16:14:49

IndexOf distingue entre mayúsculas y minúsculas. Esto se debe a que utiliza el método equals para comparar los elementos de la lista. Lo mismo va para contiene y quitar.

 -2
Author: Robbie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-14 15:42:12