Как сравнить строки без учета регистра в Kotlin? Аналог Java equalsIgnoreCase
Правильный способ: используйте equals(other, ignoreCase = true)
В Kotlin нет прямого метода equalsIgnoreCase(), как в Java, но есть гораздо более гибкий и идиоматичный подход. Класс String в Kotlin содержит метод equals() с дополнительным параметром ignoreCase.
val city = "Москва"
val userInput = "мосКВА"
if (city.equals(userInput, ignoreCase = true)) {
println("Город совпал!") // Этот код выполнится
} else {
println("Города разные")
}
Как это работает
Метод equals(other: Any?, ignoreCase: Boolean = false): Boolean — это встроенная функция Kotlin. Когда вы передаёте ignoreCase = true, сравнение выполняется без учёта регистра. По умолчанию ignoreCase = false, что эквивалентно обычному ==.
Важные нюансы
- Null-безопасность: Этот метод защищает от NullPointerException. Если
cityилиuserInputравноnull, метод вернётfalse(кроме случая, когда обаnull— тогда вернётсяtrue). - Локализация: Метод корректно работает с символами Unicode, включая кириллицу, немецкие умлауты, французские акценты и т.д.
- Производительность: В отличие от подхода
toLowerCase(), этот метод не создаёт новые строки, что экономит память.
Сравнение с Java-подходом
Для наглядности приведу таблицу соответствия:
// Java
str1.equalsIgnoreCase(str2)
// Kotlin (эквивалент)
str1.equals(str2, ignoreCase = true)
// Или с использованием infix-нотации (но только для Boolean):
// В Kotlin нет infix для equals с ignoreCase, но можно сделать extension
Дополнительные примеры
Вот несколько сценариев использования:
// Проверка ввода пользователя
fun isValidPassword(input: String): Boolean {
return "admin123".equals(input, ignoreCase = true)
}
// Сортировка списка без учёта регистра
val names = listOf("Анна", "борис", "Виктор", "антон")
val sorted = names.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it })
println(sorted) // [Анна, антон, борис, Виктор]
// Фильтрация
val cities = listOf("Москва", "Париж", "Лондон")
val search = "мос"
val filtered = cities.filter { it.startsWith(search, ignoreCase = true) }
println(filtered) // [Москва]
Когда использовать toLowerCase()?
Иногда можно встретить совет сравнивать через toLowerCase(). Избегайте этого, если нет веской причины:
// ПЛОХОЙ стиль — создаёт лишние объекты
if (city.toLowerCase() == userInput.toLowerCase()) { ... }
// ХОРОШИЙ стиль — без лишних аллокаций
if (city.equals(userInput, ignoreCase = true)) { ... }
Также помните, что toLowerCase() может давать разные результаты в зависимости от локали (например, в турецком языке буква "I" преобразуется по-особому). Метод с ignoreCase = true этого недостатка лишён.
Вывод
Для сравнения строк без учёта регистра в Kotlin всегда используйте equals(other, ignoreCase = true). Это идиоматично, безопасно и эффективно. Забудьте про Java-метод equalsIgnoreCase() — в Kotlin есть более элегантное решение.
Альтернативный подход: Extension-функция для удобства
Если вы часто сравниваете строки без учёта регистра и хотите получить синтаксис, близкий к Java, можно написать свою extension-функцию:
fun String.equalsIgnoreCase(other: String): Boolean {
return this.equals(other, ignoreCase = true)
}
// Использование
val city = "Москва"
val userInput = "мосКВА"
if (city.equalsIgnoreCase(userInput)) {
println("Равны")
}
Теперь у вас есть метод, который выглядит и ведёт себя как Java-версия, но использует Kotlin-механизмы под капотом.
Другой вариант: оператор == с приведением
Можно также переопределить поведение, но это не рекомендуется:
// Не делайте так — это нарушает ожидания
operator fun String?.compareTo(other: String?): Int {
return (this ?: "").compareTo(other ?: "", ignoreCase = true)
}
Для коллекций: contentEquals
Если сравниваете массивы символов или списки строк:
val arr1 = charArrayOf('A', 'B')
val arr2 = charArrayOf('a', 'b')
println(arr1.contentEquals(arr2, ignoreCase = true)) // true
Выберите тот способ, который лучше вписывается в ваш стиль кода. Но помните, что встроенный equals() с параметром — это самый идиоматичный и производительный вариант.