indexOf Case Sensitive?

¿Es el método indexOf (String) sensible a mayúsculas y minúsculas? Si es así, ¿hay una versión que no distinga entre mayúsculas y minúsculas?

Los métodos de indexOf() son sensibles a las mayúsculas y minúsculas. Puede hacer que (de forma aproximada, de forma discontinua, pero trabajando en muchos casos) no distinga entre mayúsculas y minúsculas al convertir sus cadenas en mayúsculas / minúsculas de antemano:

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

¿Es el método indexOf (String) sensible a mayúsculas y minúsculas?

Sí, es sensible a 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 que no distinga entre mayúsculas y minúsculas?

No, no hay. Puede convertir ambas cadenas en 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); } 

Hay un método de ignorar caso en la clase StringUtils de la biblioteca Apache Commons Lang

indexOfIgnoreCase (CharSequence str, CharSequence searchStr)

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

La mejor forma de hacer insensibilidad de casos que he encontrado es:

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

Eso hará un indexOf() caso insensible indexOf() .

Aquí está mi solución, que no asigna 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)); } 

Sí, es sensible a mayúsculas y minúsculas. Puede hacer un indexOf insensible a mayúsculas y minúsculas al convertir su String y el parámetro String en mayúsculas antes de realizar la búsqueda.

 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 será 20, ¡lo cual es incorrecto! idxL será 19, que es correcto. Lo que está causando el problema es que toUpperCase () convierte el carácter “ß” en DOS caracteres, “SS” y esto arroja el índice.

En consecuencia, siempre apegue a toLowerCase ()

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

Si lo está usando para manipular su cadena, ¿no podría 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); } } 

Acabo de mirar la fuente. Compara caracteres por lo que es sensible a mayúsculas y minúsculas.

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

Sí, estoy bastante seguro de que es así. Un método para trabajar alrededor de eso usando la biblioteca estándar sería:

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

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

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

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

Para resumir, 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.

La primera pregunta ya ha sido respondida muchas veces. Sí, los métodos String.indexOf() son sensibles a las mayúsculas y minúsculas.

Si necesita un indexOf() sensible a la configuración regional, puede usar Collator . Dependiendo del valor de la fuerza que establezca, puede obtener una comparación que no distinga entre mayúsculas y minúsculas, y también tratar las letras acentuadas igual que las sin acentos, 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; } 

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

La conversión de ambas cadenas a minúsculas generalmente no es gran cosa, pero sería lento si algunas de las cadenas son largas. Y si haces esto en un bucle, entonces sería muy malo. Por esta razón, recomendaría indexOfIgnoreCase .

indexOf distingue entre mayúsculas y minúsculas. Esto se debe a que utiliza el método equals para comparar los elementos en la lista. Lo mismo ocurre con contains y remove.

    Intereting Posts