В защиту API Java: документация о методе String.equalsIgnoreCase
никогда не утверждала, что он будет работать "как положено" в произвольных кодовых точках Юникода.В нем говорится:
Два символа c1 и c2 считаются одним и тем же регистром игнорирования, если верно хотя бы одно из следующего:
- Два символа одинаковы (каксравнивается оператором ==)
- Применение метода Character.toUpperCase (char) к каждому символу дает одинаковый результат
- Применение метода Character.toLowerCase (char) к каждому символу дает одинаковыйрезультат
Итак, в документации совершенно недвусмысленно говорится, что она применяется Character.toUpperCase
к char
с, то есть к кодовым единицам UTF-16 , а не кКодовые точки Unicode.
Если вы используете метод Character.toUpperCase(int codePoint)
для каждого кода point , то сравнение ведет себя как ожидалось.Вот краткий пример в Scala (использует тот же Java API, метод высшего порядка forall
, надо надеяться, самоочевиден):
val a = "?"
val b = "?"
(a.codePoints.toArray zip b.codePoints.toArray).forall {
case (x, y) =>
Character.toLowerCase(x) == Character.toLowerCase(y)
}
печатает
true
какожидается.Почему это?Я думаю, что можно смело винить в этом обратную совместимость.