java - w3org - indexOf Case Sensitive?
html5 official website (16)
¿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);
}
¿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?
¿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.
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));
}
Hay un método de ignorar caso en la clase StringUtils de la biblioteca Apache Commons Lang
indexOfIgnoreCase (CharSequence str, CharSequence searchStr)
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
.
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;
}
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.
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());
}
}
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()
.
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 ()
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 ;-)
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.
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);
@Test
public void testIndexofCaseSensitive() {
TestCase.assertEquals(-1, "abcDef".indexOf("d") );
}