recorrer - saber si una cadena contiene numeros java
¿Cómo verificar si una Cadena contiene otra Cadena de una manera que no distingue entre mayúsculas y minúsculas en Java? (17)
Una implementación más rápida: utilizando String.regionMatches()
El uso de expresiones regulares puede ser relativamente lento. (Ser lento) no importa si solo quiere verificar en un caso. Pero si tiene una matriz o una colección de miles o cientos de miles de cadenas, las cosas pueden ser 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. Verifica si las regiones de 2 String
coinciden, pero lo importante es que también tiene una sobrecarga con un práctico parámetro ignoreCase
.
public static boolean containsIgnoreCase(String src, String what) {
final int length = what.length();
if (length == 0)
return true; // Empty string is contained
final char firstLo = Character.toLowerCase(what.charAt(0));
final char firstUp = Character.toUpperCase(what.charAt(0));
for (int i = src.length() - length; i >= 0; i--) {
// Quick check before calling the more expensive regionMatches() method:
final char ch = src.charAt(i);
if (ch != firstLo && ch != firstUp)
continue;
if (src.regionMatches(true, i, what, 0, length))
return true;
}
return false;
}
Análisis de velocidad
Este análisis de velocidad no significa ser ciencia espacial, solo una imagen aproximada de qué tan rápido son los diferentes métodos.
Yo comparo 5 métodos.
- Nuestro método contenidosIgnoreCase () .
- Al convertir ambas cadenas en minúsculas y llamar a
String.contains()
. - Al convertir la cadena de origen a minúsculas y llamar a
String.contains()
con la subcadena de caché anterior y caché. Esta solución ya no es tan flexible porque prueba una subcadena predefinida. - Usando la expresión regular (la respuesta aceptada
Pattern.compile().matcher().find()
...) - Usando expresiones regulares pero con
Pattern
pre-creados y en caché. Esta solución ya no es tan flexible porque prueba una subcadena predefinida.
Resultados (llamando al método 10 millones de veces):
- Nuestro método: 670 ms.
- 2x toLowerCase () y contiene (): 2829 ms
- 1x toLowerCase () y contiene () con subcadena en caché: 2446 ms
- Regexp: 7180 ms
- Regexp con
Pattern
caché: 1845 ms
Resultados en una tabla:
RELATIVE SPEED 1/RELATIVE SPEED
METHOD EXEC TIME TO SLOWEST TO FASTEST (#1)
------------------------------------------------------------------------------
1. Using regionMatches() 670 ms 10.7x 1.0x
2. 2x lowercase+contains 2829 ms 2.5x 4.2x
3. 1x lowercase+contains cache 2446 ms 2.9x 3.7x
4. Regexp 7180 ms 1.0x 10.7x
5. Regexp+cached pattern 1845 ms 3.9x 2.8x
Nuestro método es 4 veces más rápido en comparación con el uso de minúsculas y minúsculas y el uso de 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 si el Pattern
está pre-almacenado en caché (y pierde la flexibilidad para buscar 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 ejecutable completa:
import java.util.regex.Pattern;
public class ContainsAnalysis {
// Case 1 utilizing String.regionMatches()
public static boolean containsIgnoreCase(String src, String what) {
final int length = what.length();
if (length == 0)
return true; // Empty string is contained
final char firstLo = Character.toLowerCase(what.charAt(0));
final char firstUp = Character.toUpperCase(what.charAt(0));
for (int i = src.length() - length; i >= 0; i--) {
// Quick check before calling the more expensive regionMatches()
// method:
final char ch = src.charAt(i);
if (ch != firstLo && ch != firstUp)
continue;
if (src.regionMatches(true, i, what, 0, length))
return true;
}
return false;
}
// Case 2 with 2x toLowerCase() and contains()
public static boolean containsConverting(String src, String what) {
return src.toLowerCase().contains(what.toLowerCase());
}
// The cached substring for case 3
private static final String S = "i am".toLowerCase();
// Case 3 with pre-cached substring and 1x toLowerCase() and contains()
public static boolean containsConverting(String src) {
return src.toLowerCase().contains(S);
}
// Case 4 with regexp
public static boolean containsIgnoreCaseRegexp(String src, String what) {
return Pattern.compile(Pattern.quote(what), Pattern.CASE_INSENSITIVE)
.matcher(src).find();
}
// The cached pattern for case 5
private static final Pattern P = Pattern.compile(
Pattern.quote("i am"), Pattern.CASE_INSENSITIVE);
// Case 5 with pre-cached Pattern
public static boolean containsIgnoreCaseRegexp(String src) {
return P.matcher(src).find();
}
// Main method: perfroms speed analysis on different contains methods
// (case ignored)
public static void main(String[] args) throws Exception {
final String src = "Hi, I am Adam";
final String what = "i am";
long start, end;
final int N = 10_000_000;
start = System.nanoTime();
for (int i = 0; i < N; i++)
containsIgnoreCase(src, what);
end = System.nanoTime();
System.out.println("Case 1 took " + ((end - start) / 1000000) + "ms");
start = System.nanoTime();
for (int i = 0; i < N; i++)
containsConverting(src, what);
end = System.nanoTime();
System.out.println("Case 2 took " + ((end - start) / 1000000) + "ms");
start = System.nanoTime();
for (int i = 0; i < N; i++)
containsConverting(src);
end = System.nanoTime();
System.out.println("Case 3 took " + ((end - start) / 1000000) + "ms");
start = System.nanoTime();
for (int i = 0; i < N; i++)
containsIgnoreCaseRegexp(src, what);
end = System.nanoTime();
System.out.println("Case 4 took " + ((end - start) / 1000000) + "ms");
start = System.nanoTime();
for (int i = 0; i < N; i++)
containsIgnoreCaseRegexp(src);
end = System.nanoTime();
System.out.println("Case 5 took " + ((end - start) / 1000000) + "ms");
}
}
Digamos que tengo dos cuerdas,
String s1 = "AbBaCca";
String s2 = "bac";
Quiero realizar una verificación que devuelva que s2
está contenido dentro de 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 al leer la documentación. Si es así, supongo que mi mejor método sería algo como:
return s1.toLowerCase().contains(s2.toLowerCase());
Dejando esto de lado, ¿hay otra forma (posiblemente mejor) de lograr esto sin preocuparse por la sensibilidad a las mayúsculas y minúsculas?
Aquí hay algunos que son amigables con Unicode que puedes hacer si tiras de ICU4j. Supongo que "ignorar el caso" es cuestionable para los nombres de los métodos porque aunque las comparaciones de fuerza primaria ignoran el caso, se describe como las características específicas 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.
public static boolean containsIgnoreCase(String haystack, String needle) {
return indexOfIgnoreCase(haystack, needle) >= 0;
}
public static int indexOfIgnoreCase(String haystack, String needle) {
StringSearch stringSearch = new StringSearch(needle, haystack);
stringSearch.getCollator().setStrength(Collator.PRIMARY);
return stringSearch.first();
}
Hice una prueba para encontrar una coincidencia que no distingue entre mayúsculas y minúsculas de una cadena. Tengo un vector de 150,000 objetos, todos con una cadena como un campo y quería encontrar el subconjunto que coincidía con una cadena. Probé tres métodos:
Convertir todo a minúsculas
for (SongInformation song: songs) { if (song.artist.toLowerCase().indexOf(pattern.toLowercase() > -1) { ... } }
Usa el método String matches ()
for (SongInformation song: songs) { if (song.artist.matches("(?i).*" + pattern + ".*")) { ... } }
Usar expresiones regulares
Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(""); for (SongInformation song: songs) { m.reset(song.artist); if (m.find()) { ... } }
Los resultados del tiempo son:
No intento de partido: 20 msegs
Para bajar de partido: 182 msegs.
Coincidencias de cadena: 278 msecs
Expresión regular: 65 msegs.
La expresión regular parece ser la más rápida para este caso de uso.
No estoy seguro de cuál es su pregunta principal aquí, pero sí, .contains distingue entre mayúsculas y minúsculas.
Otro método fácil de usar para encontrar una cadena dentro de una cadena es STRING.INDEXOF ()
String str = new String("Welcome");
System.out.print("Found Index :" );
System.out.println(str.indexOf( ''o'' ));
Índice encontrado: 4
www.tutorialspoint.com/java/java_string_indexof.htm
Puedes usar
org.apache.commons.lang3.StringUtils.containsIgnoreCase("AbBaCca", "bac");
La biblioteca de Apache Commons es muy útil para este tipo de cosas. Y este en particular puede ser mejor que las expresiones regulares, ya que la expresión regular siempre es costosa en términos de rendimiento.
Puedes usar expresiones regulares , y funciona:
boolean found = s1.matches("(?i).*" + s2+ ".*");
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:
Pattern.compile(Pattern.quote(wantedStr), Pattern.CASE_INSENSITIVE).matcher(source).find();
EDITAR: Si s2 contiene caracteres especiales de expresiones regulares (de los cuales hay muchos), es importante citarlo primero. He corregido mi respuesta ya que es la primera que verá la gente, pero vota por la de Matt Quail ya que lo señaló.
Sí, esto es alcanzable:
String s1 = "abBaCca";
String s2 = "bac";
String s1Lower = s1;
//s1Lower is exact same string, now convert it to lowercase, I left the s1 intact for print purposes if needed
s1Lower = s1Lower.toLowerCase();
String trueStatement = "FALSE!";
if (s1Lower.contains(s2)) {
//THIS statement will be TRUE
trueStatement = "TRUE!"
}
return trueStatement;
Este código devolverá la cadena "VERDADERO!" Como se encontró que tus personajes estaban contenidos.
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:
- Caso 1 tomó 2788 ms - regiónMatches
- Caso 2 tomó 1520 ms - mi
El código:
public static String lowerCaseAscii(String s) {
if (s == null)
return null;
int len = s.length();
char[] buf = new char[len];
s.getChars(0, len, buf, 0);
for (int i=0; i<len; i++) {
if (buf[i] >= ''A'' && buf[i] <= ''Z'')
buf[i] += 0x20;
}
return new String(buf);
}
public static boolean containsIgnoreCaseAscii(String str, String searchStr) {
return StringUtils.contains(lowerCaseAscii(str), lowerCaseAscii(searchStr));
}
Simplemente podrías hacer algo como esto:
String s1 = "AbBaCca";
String s2 = "bac";
String toLower = s1.toLowerCase();
return toLower.contains(s2);
Un problema con la respuesta de Dave L. es cuando s2 contiene el regex como, por ejemplo, /d
, etc.
Quieres llamar a Pattern.quote () en s2:
Pattern.compile(Pattern.quote(s2), Pattern.CASE_INSENSITIVE).matcher(s1).find();
Una forma más sencilla de hacer esto (sin preocuparse por la coincidencia de patrones) sería convertir ambas String
en minúsculas:
String foobar = "fooBar";
String bar = "FOO";
if (foobar.toLowerCase().contains(bar.toLowerCase()) {
System.out.println("It''s a match!");
}
"AbCd".toLowerCase().contains("abcD".toLowerCase())
String container = " Case SeNsitive ";
String sub = "sen";
if (rcontains(container, sub)) {
System.out.println("no case");
}
public static Boolean rcontains(String container, String sub) {
Boolean b = false;
for (int a = 0; a < container.length() - sub.length() + 1; a++) {
//System.out.println(sub + " to " + container.substring(a, a+sub.length()));
if (sub.equalsIgnoreCase(container.substring(a, a + sub.length()))) {
b = true;
}
}
return b;
}
Básicamente, es un método que toma dos cadenas. Se supone que es una versión que no distingue entre mayúsculas y minúsculas de contiene (). Cuando se utiliza el método de contenido, desea ver si una cadena está contenida en la otra.
Este método toma la cadena que es "sub" y verifica si es igual a las subcadenas de la cadena del contenedor que tienen la misma longitud que la "sub". Si observa el bucle for
, verá que se 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 es equalsIgnoreCase
al sub.
String x="abCd";
System.out.println(Pattern.compile("c",Pattern.CASE_INSENSITIVE).matcher(x).find());
import java.text.Normalizer;
import org.apache.commons.lang3.StringUtils;
public class ContainsIgnoreCase {
public static void main(String[] args) {
String in = " Annulée ";
String key = "annulee";
// 100% java
if (Normalizer.normalize(in, Normalizer.Form.NFD).replaceAll("[//p{InCombiningDiacriticalMarks}]", "").toLowerCase().contains(key)) {
System.out.println("OK");
} else {
System.out.println("KO");
}
// use commons.lang lib
if (StringUtils.containsIgnoreCase(Normalizer.normalize(in, Normalizer.Form.NFD).replaceAll("[//p{InCombiningDiacriticalMarks}]", ""), key)) {
System.out.println("OK");
} else {
System.out.println("KO");
}
}
}