Comprender la lógica en CaseInsensitiveComparator

Normalmente, esperaríamos convertir el caso una vez y comparar y terminar con él. Sin embargo, el código convierte el caso dos veces, y la razón se indica en el comentario sobre un método diferente public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len):

Desafortunadamente, la conversión a mayúsculas no funciona correctamente para el alfabeto georgiano, que tiene reglas extrañas sobre la conversión de mayúsculas y minúsculas. Por lo tanto, debemos hacer una última comprobación antes de salir.


Apéndice

El código de regionMatchestiene algunas diferencias con el código en el CaseInsenstiveComparator, pero esencialmente hace lo mismo. El código completo del método se cita a continuación con fines de verificación cruzada:

public boolean regionMatches(boolean ignoreCase, int toffset,
                       String other, int ooffset, int len) {
    char ta[] = value;
    int to = offset + toffset;
    char pa[] = other.value;
    int po = other.offset + ooffset;
    // Note: toffset, ooffset, or len might be near -1>>>1.
    if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) ||
            (ooffset > (long)other.count - len)) {
        return false;
    }
    while (len-- > 0) {
        char c1 = ta[to++];
        char c2 = pa[po++];
        if (c1 == c2) {
            continue;
        }
        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;
            }
        }
        return false;
    }
    return true;
}
Respuesta 1

Del estándar técnico de Unicode :

Además, debido a los caprichos del lenguaje natural, hay situaciones en las que dos caracteres Unicode diferentes tienen las mismas mayúsculas o minúsculas

Por lo tanto, no es suficiente comparar solo mayúsculas de dos caracteres, ya que pueden tener diferentes mayúsculas y las mismas minúsculas

La simple verificación de la fuerza bruta da algunos resultados. Verifique, por ejemplo, los puntos de código 73 y 304:

char ch1 = (char) 73; //LATIN CAPITAL LETTER I
char ch2 = (char) 304; //LATIN CAPITAL LETTER I WITH DOT ABOVE
System.out.println(ch1==ch2);
System.out.println(Character.toUpperCase(ch1)==Character.toUpperCase(ch2));
System.out.println(Character.toLowerCase(ch1)==Character.toLowerCase(ch2));

Salida:

false
false
true

Entonces "İ" e "I" no son iguales entre sí. Ambos personajes son mayúsculas. Pero comparten la misma letra minúscula: "i" y eso da una razón para tratarlos como los mismos valores en una comparación insensible a mayúsculas y minúsculas.

Respuesta: 2

En otra respuesta, la configuración regional predeterminada ya dio un ejemplo de por qué comparar solo mayúsculas no es suficiente, es decir, la letra ASCII "I" y la I mayúscula con el punto "İ".

Ahora podría preguntarse, ¿por qué no solo comparan solo minúsculas en lugar de mayúsculas y minúsculas, si detecta más casos que mayúsculas? La respuesta es que no detecta más casos, simplemente encuentra diferentes casos.

Tome la letra "ı" ( (char)305, i sin puntos pequeños) y la ascii "i". Son diferentes, sus minúsculas son diferentes, pero comparten la misma letra mayúscula "I".

Y finalmente, compare el capital I con el punto "İ" con el pequeño sin punto i "ı". Ni sus mayúsculas ("İ" vs. "I") ni sus minúsculas ("i" vs. "ı") coinciden, pero las minúsculas de sus mayúsculas son las mismas ("I"). Encontré otro caso si este fenómeno, en las letras griegas "ϴ" y "ϑ" (char 1012 y 977).

Por lo tanto, una verdadera comparación entre mayúsculas y minúsculas ni siquiera puede verificar las mayúsculas y minúsculas de los caracteres originales , sino que debe verificar las minúsculas de las mayúsculas.

Respuesta: 3

Considere los siguientes caracteres: fy F. La ifdeclaración inicial volvería falseporque no coinciden. Sin embargo, si capitaliza ambos caracteres, obtendrá Fy F. Entonces coincidirían. Lo mismo no sería cierto para, digamos, cy G.

El código es eficiente. No es necesario poner en mayúscula ambos caracteres si ya coinciden (de ahí la primera ifdeclaración). Sin embargo, si no coinciden, debemos verificar si difieren solo en el caso (de ahí la segunda ifdeclaración).

La ifdeclaración final se usa para ciertos alfabetos (como el georgiano) donde la capitalización es un asunto complicado. Para ser honesto, no sé mucho sobre cómo funciona eso (¡solo confía en que Oracle lo hace!).

Respuesta: 4

Estoy buscando 2 o 3 de las bibliotecas más comunes / utilizadas en la industria para la plataforma Java para la creación de archivos PDF sobre la marcha. El único requisito en el que me estoy centrando es la capacidad de usar ...

Este código que se usó en algunas circunstancias para tratar imágenes individuales arrastradas y soltadas de ciertos navegadores web (firefox) no dio problemas en 1.8.0_25 image = (Image) trans.getTransferData ("...

Estoy buscando construir un generador de feeds para RSS y Atom. He estado buscando una biblioteca que genere una amplia variedad de formatos (RSS .9 a través de lo que sea actual, y Atom .3 ...

Estoy escribiendo un programa que carga todas las clases de una carpeta específica. Algunas de las clases están creando objetos en bloque estático y estos objetos a su vez están haciendo algunas llamadas nativas durante su ...