Почему String.equalsIgnoreCase сравнивает как прописные, так и строчные версии отдельных символов?

Я просматривал декомпилированные исходные коды класса Java SE7 String, в частности метод equalsIgnoreCase, и мне показалась странной следующая строка (выполняется в цикле while, локальные переменные опущены):

if (((c1 = this.value[(o1++)]) != (c2 = target[(o2++)])) 
    && (toUpperCase(c1) != toUpperCase(c2)) 
    && (toLowerCase(c1) != toLowerCase(c2))) { 
        return false; 
}

И мне стало интересно, почему c1 и c2 проверяются на неравноправие как в верхнем, так и в нижнем регистре. Конечно, если бы сравнение в верхнем регистре было равным, нижний регистр никогда бы даже не был достигнут ... из этого, однако, я пришел к выводу, что есть случаи, когда верхний регистр (c1)! = верхний регистр (c2) И символы по-прежнему равны, когда сравнивается в нижнем регистре.

Предложения кто-нибудь?


person Peter Perháč    schedule 27.08.2014    source источник
comment
Может ли быть так, что некоторые нелатинские символы сравниваются с одинаковыми прописными и не строчными буквами, или наоборот? В любом случае, хороший вопрос.   -  person Mena    schedule 27.08.2014
comment
@Mena - На самом деле это нехорошо. 1) Это дубликат. 2) Ответ находится в комментариях к исходному коду, а исходный код находится в свободном доступе из нескольких мест.   -  person Stephen C    schedule 27.08.2014
comment
@StephenC Ой. Должен был сделать мою домашнюю работу.   -  person Mena    schedule 27.08.2014


Ответы (2)


Настоящий исходный код Java для equalsIgnoreCase выглядит следующим образом:

public boolean equalsIgnoreCase(String anotherString) {
    return (this == anotherString) ? true
            : (anotherString != null)
            && (anotherString.value.length == value.length)
            && regionMatches(true, 0, anotherString, 0, value.length);
}

Код, о котором вы говорите, находится в regionMatches, а вот соответствующий раздел с оригинальными комментариями:

        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;
            }
        }

Урок: не тратьте время на просмотр декомпилированного кода, когда фактический исходный код находится в свободном доступе... как в случае с библиотеками Java. На самом деле, исходный код библиотек Java был включен в JDK столько, сколько я себя помню, когда искал его.

Использованная литература:

person Stephen C    schedule 27.08.2014

Из этой ссылки кажется, что есть локали, в которых некоторые прописные и строчные буквы не совпадают. . Используемый пример - турецкий, где

if (x.toLowerCase().equals("list"))

не вернет true для x="LIST".

Я подозреваю, что таких случаев несколько, поэтому можно либо указать локаль, которая, по-видимому, может вызвать множество других сбоев, либо сравнить оба случая. Так что в основном есть примеры, когда буквы могут быть одинаковыми в одном случае, а не в другом

person Trudbert    schedule 27.08.2014