TGViewer
Java: fill the gaps Java: fill the gaps @java_fillthegaps · 12.3K subscribers
Post #412 7.1K
​Как сравнить строки без учёта регистра

В этом посте расскажу, как решить задачу из предыдущего поста и сделать метод быстрее, чем в JDK.

Напомню задачу: сравнить две строки без учёта регистра и оценить производительность в разных ситуациях.

Шаг 1. Смотрим подходящие методы в классе String

s1.toLowerCase().equals(s2.toLowerCase())
s1.equalsIgnoreCase(s2)
s1.compareToIgnoreCase(s2) != 0
s1.regionMatches(true, 0, s2, 0, s2.length())

Шаг 2. Предположим возможные ситуации

Строки могут сильно и слабо отличаться по регистру.

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

Шаг 3. Углубляемся в реализацию

🔸 toLowerCase + equals

▫️ Для каждой строки создаёт копию в нижнем регистре. Затем включается обычный equals:
▫️ Сравнивает длины строк. Если не равны, сразу возвращается false
▫️ Сравнивает по одному символу, пока не дойдёт до конца строки или пока символы не будут разными

✖️В начале целиком обходим s1 и s2, чтобы создать копии в нижнем регистре. Когда длины строк отличаются (что можно узнать сразу), эта работа бесполезна
✖️ Если строки мало отличаются по регистру, то приведение всех символов к одному регистру будет лишним

🔸 compareToIgnoreCase cравнивает элементы по порядку. Если символы не равны — вызывает апперкейс и сравнивает ещё раз.

✔️ Uppercase происходит только при необходимости. Если разница в регистрах небольшая (s1=java, s2=Java), то этот подход будет быстрее
✖️ Цель метода — сравнить строки, поэтому нет быстрой проверки длины

🔸 regionMatches берёт символы из строк s1 и s2, сразу делает uppercase и сравнивает

✔️ Если строки по регистрам сильно отличаются, предварительный апперкейс ускорит проверку
✖️ Метод работает с подстроками произвольной длины, поэтому нет быстрой проверки длин

🔸 equalsIgnoreCase сравнивает длины строк, потом вызывает regionMatches

Итог

▪️ Если строки разной длины, то однозначно побеждает equalsIgnoreCase
▪️ Если длины одинаковы и
— регистры не сильно отличаются, то побеждает compareToIgnoreCase
— нужно много преобразований — regionMatches

equalsIgnoreCase для каждого символа делается апперкейс. Если строки по регистрам слабо отличаются, то это явно лишнее. Для таких случаев подойдёт кастомный метод:

if (s1.length() != s2.length()) {
return false;
}
return s1.compareToIgnoreCase(s2) != 0;

Лучшее из двух миров — быстрая проверка по длине и нет лишних апперкейсов.

Ниже — бенчмарки всех вариантов. Результаты на разных железках могут отличаться!
  • 🔥 70
  • 👍 37
  • 👎 6
More from @java_fillthegaps
  1. Apr 30, 2026Get Your Hands Dirty on Clean Architecture: отзыв на книгу Когда я подняла тему чистой арх…
  2. Apr 27, 2026​Clean Architecture: отзыв на книгу Наконец-то дочитала книгу Clean Architecture Роберта М…
  3. Mar 4, 2026Как переиспользовать контекст в интеграционных тестах Сегодня расскажу базовый минимум для…
  4. Mar 4, 2026Post #660
  5. Mar 4, 2026Тестовый контекст поднимается 2 минуты. У нас 4 класса с интеграционными тестами, их конфи…
  6. Feb 25, 2026Чистая архитектура. Главы 3-5 Продолжаем спидран по Clean Architecture Роберта Мартина. ⭐️…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →