Digamos que tengo dos cuerdas
String s1 = "AbBaCca";
String s2 = "bac";
Quiero realizar una comprobación de devolución que s2
está contenida dentro s1
. Puedo hacer esto con:
return s1.contains(s2);
Estoy bastante seguro de que contains()
distingue entre mayúsculas y minúsculas, sin embargo, no puedo determinar esto con seguridad leyendo la documentación. Si es así, supongo que mi mejor método sería algo como:
return s1.toLowerCase().contains(s2.toLowerCase());
Dejando de lado todo esto, ¿hay otra manera (posiblemente mejor) de lograr esto sin preocuparse por la sensibilidad a mayúsculas y minúsculas?
Respuestas:
Sí, contiene mayúsculas y minúsculas. Puede usar java.util.regex.Pattern con el indicador CASE_INSENSITIVE para la coincidencia entre mayúsculas y minúsculas:
EDITAR: si s2 contiene caracteres especiales regex (de los cuales hay muchos), es importante citarlo primero. He corregido mi respuesta, ya que es la primera que verán las personas, pero vote por la de Matt Quail desde que señaló esto.
fuente
Pattern.CASE_INSENSITIVE
, esto funciona solo para caracteres ASCII (es decir, "Ä" no coincidirá con "ä"). Uno necesita especificar adicionalmente laUNICODE_CASE
bandera para lograr eso.Pattern
más rendimiento ques1.toLowerCase().contains(s2.toLowerCase())
?Pattern.compile(Pattern.quote(needle), Pattern.CASE_INSENSITIVE).matcher(haystack).find()
Un problema con la respuesta de Dave L. es cuando s2 contiene marcas de expresiones regulares como
\d
, etc.Desea llamar a Pattern.quote () en s2:
fuente
toLowerCase().contains()
es más rápido.Pattern.UNICODE_CASE
bandera también. ¿Podría por favor confirmar esto?Puedes usar
La biblioteca Apache Commons es muy útil para este tipo de cosas. Y esta en particular puede ser mejor que las expresiones regulares, ya que la expresión regular siempre es costosa en términos de rendimiento.
fuente
String.regionMatches
, que utiliza conversiones de caracteres, por lo que no. Por otra parte,containsIgnoreCase("ß", "ss")
devuelve -1, lo que es malo en todos los sitios (los alemanes "s" afilados capitaliza a "ss".Una implementación más rápida: utilización
String.regionMatches()
Usar regexp puede ser relativamente lento. (Ser lento) no importa si solo quieres verificar en un caso. Pero si tiene una matriz o una colección de miles o cientos de miles de cadenas, las cosas pueden volverse bastante lentas.
La solución presentada a continuación no usa expresiones regulares ni
toLowerCase()
(que también es lenta porque crea otras cadenas y las tira después de la comprobación).La solución se basa en el método String.regionMatches () que parece ser desconocido. Comprueba si 2
String
regiones coinciden, pero lo importante es que también tiene una sobrecarga con unignoreCase
parámetro útil .Análisis de velocidad
Este análisis de velocidad no significa ser ciencia de cohetes, solo una imagen aproximada de lo rápido que son los diferentes métodos.
Comparo 5 métodos.
String.contains()
.String.contains()
con la subcadena pre-almacenada en caché y en minúsculas. Esta solución ya no es tan flexible porque prueba una subcadena predefinida.Pattern.compile().matcher().find()
...)Pattern
. Esta solución ya no es tan flexible porque prueba una subcadena predefinida.Resultados (llamando al método 10 millones de veces):
Pattern
: 1845 msResultados en una tabla:
Nuestro método es 4 veces más rápido en comparación con las minúsculas y el uso
contains()
, 10 veces más rápido en comparación con el uso de expresiones regulares y también 3 veces más rápido incluso siPattern
está pre-almacenado en caché (y pierde la flexibilidad de verificar una subcadena arbitraria).Código de prueba de análisis
Si está interesado en cómo se realizó el análisis, aquí está la aplicación completa ejecutable:
fuente
ß
(alemán S agudo; capitaliza aSS
) y también para algunos otros caracteres (vea la fuente deString.regionMatches
, que intenta ambas conversiones).StringUtils.containsIgnoreCase()
es que tanto mi solución como la de Apache usan unregionMatches()
método (en un ciclo), pero incluso eso no es lo mismo que llamoString.regionMatches()
y las llamadas de ApacheCharSequenceUtils.regionMatches()
.CharSequenceUtils.regionMatches
solo llama enString.regionMatches
realidad. De todos modos, mi punto era dar la información, que si alguien ya está usando StringUtils lib, simplemente puede llamarlo porque parece ser una forma eficiente como lo demuestra con su punto de referencia. Si no estuviera usando Apache lib, definitivamente usaría su método;)Una forma más simple de hacer esto (sin preocuparse por la coincidencia de patrones) sería convertir ambos
String
s en minúsculas:fuente
Sí, esto se puede lograr:
Este código devolverá la cadena "¡VERDADERO!" ya que descubrió que tus personajes estaban contenidos.
fuente
s2
. Sin hablar de detalles como este, este no se compila y, si lo hiciera, devolvería una cadena.Puede usar expresiones regulares , y funciona:
fuente
Aquí hay algunos compatibles con Unicode que puede hacer si tira de ICU4j. Supongo que "ignorar mayúsculas y minúsculas" es cuestionable para los nombres de métodos porque, aunque las comparaciones de fuerza primarias ignoran mayúsculas y minúsculas, se describen como los detalles que dependen de la configuración regional. Pero es de esperar que dependa de la ubicación de una manera que el usuario esperaría.
fuente
Hice una prueba para encontrar una coincidencia entre mayúsculas y minúsculas de una cadena. Tengo un Vector de 150,000 objetos, todos con una Cadena como un solo campo y quería encontrar el subconjunto que coincidía con una cadena. Probé tres métodos:
Convertir todo a minúsculas
Use el método String coincide con ()
Usa expresiones regulares
Los resultados del tiempo son:
Sin intento de coincidencia: 20 ms
Para reducir la coincidencia: 182 ms
Cadenas: 278 ms.
Expresión regular: 65 ms.
La expresión regular parece ser la más rápida para este caso de uso.
fuente
Hay una manera simple y concisa, utilizando la bandera regex (mayúsculas y minúsculas {i}):
fuente
No estoy seguro de cuál es su pregunta principal aquí, pero sí, .contains distingue mayúsculas de minúsculas.
fuente
Básicamente, es un método que toma dos cadenas. Se supone que es una versión sin distinción entre mayúsculas y minúsculas de contiene (). Cuando se utiliza el método contiene, desea ver si una cadena está contenida en la otra.
Este método toma la cadena que es "sub" y comprueba si es igual a las subcadenas de la cadena de contenedor que tienen la misma longitud que la "sub". Si observa el
for
bucle, verá que itera en subcadenas (que son la longitud del "sub") sobre la cadena del contenedor.Cada iteración verifica si la subcadena de la cadena del contenedor está
equalsIgnoreCase
en la sub.fuente
Si tiene que buscar una cadena ASCII en otra cadena ASCII, como una URL , encontrará que mi solución es mejor. He probado el método de icza y el mío para la velocidad y aquí están los resultados:
El código:
fuente
fuente
fuente
Podemos usar stream con anyMatch y contiene Java 8
fuente
o puede usar un enfoque simple y simplemente convertir el caso de la cadena en el caso de la subcadena y luego usar el método contiene.
fuente
fuente
Simplemente podrías hacer algo como esto:
fuente