utiliza que para minusculas mayusculas ignorar equalsignorecase and java string performance ignore-case

que - ignorar mayusculas y minusculas java



¿Por qué es String.equalsIgnoreCase es tan lento? (5)

Encontré una pregunta en la entrevista para escribir un método para buscar palabras similares independientemente de los casos de personajes.

Lo respondí utilizando la diferencia del valor ASCII para cada par de caracteres. Pero en casa, cuando pasé por la implementación real en String.class, me siento perturbado: ¿por qué se implementa de esa manera?

Intenté hacer una comparación entre el método incorporado y mi método personalizado, de esta manera ...

public class EqualsIgnoreCase { public static void main(String[] args) { String str1 = "Srimant @$ Sahu 959s"; String str2 = "sriMaNt @$ sAhu 959s"; System.out.println("Avg millisecs with inbuilt () - " + averageOfTenForInbuilt(str1, str2)); System.out.println("/nAvg millisecs with custom () - " + averageOfTenForCustom(str1, str2)); } public static int averageOfTenForInbuilt(String str1, String str2) { int avg = 0; for (int itr = 0; itr < 10; itr++) { long start1 = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { str1.equalsIgnoreCase(str2); } avg += System.currentTimeMillis() - start1; } return avg / 10; } public static int averageOfTenForCustom(String str1, String str2) { int avg = 0; for (int itr = 0; itr < 10; itr++) { long start2 = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { isEqualsIgnoreCase(str1, str2); } avg += System.currentTimeMillis() - start2; } return avg / 10; } public static boolean isEqualsIgnoreCase(String str1, String str2) { int length = str1.length(); if (str2.length() != length) { return false; } for (int i = 0; i < length; i++) { char ch1 = str1.charAt(i); char ch2 = str2.charAt(i); int val = Math.abs(ch1 - ch2); if (val != 0) { if (isInAlphabetsRange(ch1, ch2)) { if (val != 32) { return false; } } else { return false; } } } return true; } public static boolean isInAlphabetsRange(char ch1, char ch2) { return (((ch1 <= 122 && ch1 >= 97) || (ch1 <= 90 && ch1 >= 65)) && ((ch2 <= 122 && ch2 >= 97) || (ch2 <= 90 && ch2 >= 65))); } }

Salida-

Milisegs prom. Con incorporados () - 14

Milisegs prom. Con custom () - 5

Descubrí que el método incorporado está alcanzando la eficiencia, debido a la gran cantidad de controles y llamadas de métodos. ¿Hay alguna razón específica detrás de tal implementación? ¿O me estoy perdiendo algo en mi lógica?

Cualquier sugerencia, será muy apreciada!


Creo que este extracto de String.java es relevante:

if (ignoreCase) { // If characters don''t match but case may be ignored, // try converting both characters to uppercase. // If the results match, then the comparison scan should // continue. char u1 = Character.toUpperCase(c1); char u2 = Character.toUpperCase(c2); if (u1 == u2) { continue; } // Unfortunately, conversion to uppercase does not work properly // for the Georgian alphabet, which has strange rules about case // conversion. So we need to make one last check before // exiting. if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { continue; } }


Creo que la comprobación de

String1.equalsIgnoreCase(String2)

el que se proporciona tiene una aceptación de caracteres mucho mejor y acepta todo tipo de valores de caracteres incluidos en Unicode ; Lo que has tratado de descubrir a través de tu código personalizado es que estás comparando solo los caracteres alfabéticos en inglés.

Por lo tanto, creo que, en la línea de Pavel Horel , el comentarista de tu publicación, que debido a la sofisticación que proporciona para la comparación entre todos los tipos de personajes de Unicode, podría llevar más tiempo.


Esta podría no ser la única razón, pero el hecho de que su solución no funcione para todas las cadenas posibles es definitivamente un factor.

Hay algunas configuraciones regionales (molestas) para las cuales dos caracteres pueden tener la misma mayúscula pero no la misma minúscula. Por este motivo, para que funcione (la mayoría de las veces, consulte turco), la implementación canónica debe comparar las cadenas char-for-char en sus mayúsculas y minúsculas.

Su implementación es probablemente perfecta el 99% del tiempo, especialmente si solo tiene que lidiar con la configuración regional en inglés, pero la implementación de la biblioteca central desafortunadamente no puede hacer tales suposiciones.


Su método es incorrecto de muchas maneras. Por ejemplo, considera "!" igual a "B", "B" igual a "1", pero "!" no es igual a "1" (por lo que no es transitivo, ya que esperaríamos que fuera un método igual).

Sí, es bastante fácil escribir una implementación incorrecta para ese método que es más rápido y más simple. Un desafío razonable sería escribir uno correcto, es decir, que maneje correctamente todos los argumentos que la implementación de JDK hace.

Quizás también desee ver ¿Cómo escribo un micro-benchmark correcto en Java? para obtener mediciones de rendimiento más confiables.


Tu rutina solo maneja caracteres ASCII. El sistema uno maneja todos los caracteres Unicode.

Considere el siguiente ejemplo:

public class Test { public static void main(String[] args) { System.out.println((int) ''ě''); // => 283 System.out.println((int) ''Ě''); // => 282 } }