Поиск подстроки в строке без учета регистра: решение на Java

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Если необходимо установить, содержит ли одна строка (String) другую без учета регистра, можно привести обе строки к нижнему или верхнему регистру с помощью методов toLowerCase() или toUpperCase() перед применением contains(). Альтернативным подходом является использование Pattern с флагом CASE_INSENSITIVE:

Java
Скопировать код
String str = "Привет Мир!";
String searchStr = "мир";

boolean containsIgnoreCase = str.toLowerCase().contains(searchStr.toLowerCase());

boolean containsRegex = Pattern.compile(Pattern.quote(searchStr), Pattern.CASE_INSENSITIVE).matcher(str).find();

System.out.println("Содержит ли строка, не учитывая регистр: " + containsIgnoreCase);
System.out.println("С использованием Regex регистр также не учитывается: " + containsRegex);

Заметьте, что для сравнения используются методы toLowerCase() и toUpperCase(), в то время как Pattern с CASE_INSENSITIVE используется для поиска по шаблону.

Кинга Идем в IT: пошаговый план для смены профессии

Полезные инструменты от Apache Commons

Если вас утомляет написание длинных выражений для простых проверок, обратите внимание на инструменты из Apache Commons Lang и воспользуйтесь методом StringUtils.containsIgnoreCase:

Java
Скопировать код
boolean containsIgnoreCase = StringUtils.containsIgnoreCase(str, searchStr);

Этот метод сделает вашу работу проще и уменьшит нагрузку на систему, избегая использования ресурсоёмких регулярных выражений. В результате ваш код будет чистым и понятным, особенно если у вас уже есть зависимость от commons.

Эффективная проверка на null

Независимо от того, какой метод вы выбираете, всегда выполняйте проверку строк на null, чтобы не столкнуться с NullPointerException:

Java
Скопировать код
if (str != null && searchStr != null) {
    // проведите проверку, не учитывая регистр
}

В качестве альтернативы можно воспользоваться утилитой Apache Commons Lang, которая выполняет все необходимые действия за вас:

Java
Скопировать код
boolean containsIgnoreCase = StringUtils.containsIgnoreCase(str, searchStr);

Метод containsIgnoreCase корректно обрабатывает null-значения, возвращая false и не вызывая исключения.

Вопросы производительности

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

Однако не стоит беспокоиться: использование Pattern с предварительно скомпилированными шаблонами регулярных выражений поможет вам в тех случаях, когда поиск проводится часто:

Java
Скопировать код
Pattern pattern = Pattern.compile(Pattern.quote(searchStr), Pattern.CASE_INSENSITIVE);

boolean containsIgnoreCase = pattern.matcher(str).find();

Метод Pattern.quote() очень полезен, когда в строке, которую вы ищете, есть специальные символы регулярных выражений, но не забывайте об оптимизации производительности — от него следует отказаться, когда это не обязательно.

Умение работать с Regex, сделайте это самостоятельно!

Если вы предпочитаете работать без сторонних библиотек и не хотите нагружать систему использованием регулярных выражений, вам пригодится метод String.regionMatches:

Java
Скопировать код
public static boolean containsIgnoreCase(String str, String searchStr) {
    if (str == null || searchStr == null) return false;
    final int length = searchStr.length();
    if (length == 0) return true;

    for (int i = str.length() – length; i >= 0; i--) {
        if (str.regionMatches(true, i, searchStr, 0, length)) {
            return true;
        }
    }
    return false;
}

Метод regionMatches позволяет сравнивать части строки без учета регистра, избегая преобразования всей строки к одному регистру и использования сторонних библиотек.

Визуализация

Представьте, что у нас есть две банки, наполненные буквами различного регистра:

Markdown
Скопировать код
Банка А (🪣): [А, б, в, д, е, ж, ...]

А также маленькая банка "abc", где буквы расположены в произвольном порядке:

Markdown
Скопировать код
Банка B (🥄): [а, б, в]

Метод String.equalsIgnoreCase() работает следующим образом:

Java
Скопировать код
canString.toLowerCase().contains(popCanString.toLowerCase());

Он позволяет найти меньшую банку в большой, независимо от регистра букв:

Markdown
Скопировать код
🪣: [А, б, в, д, е, ж, ...] ищет 🥄: [а, б, в]
Результат: ✅ Найдено

Метод приводит все буквы к одному регистру, что облегчает поиск, и разные комбинации букв уже не смогут его запутать:

Markdown
Скопировать код
🪣: [а, б, в, д, е, ж, ...] также находит 🥄: [а, б, в]

Таким образом, поиск становится простым отслеживанием совпадения формы, не затрудненным разным написанием букв.

Надежный поиск без учета регистра

При создании функциональности поиска без учета регистра важно учитывать длину искомой строки:

  • Если строка поиска длинная, возможно пропустить совпадения.
  • Если строка поиска короткая, может быть больше ложных срабатываний, чем вы ожидаете.

Также следует учесть частоту и контекст использования операции поиска:

  • Для частого использования или трудоемких заданий лучше использовать предварительно скомпилированные шаблоны regex.
  • Для менее интенсивных заданий комбинация toLowerCase()/toUpperCase() и contains() может быть хорошим компромиссом между простотой и производительностью.

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

Полезные материалы

  1. Как проверить, содержит ли строка другую строку без учета регистра в Java? – Stack Overflow — содержательное обсуждение на Stack Overflow, предлагающее несколько вариантов решения задачи поиска без учета регистра.
  2. String (Java Platform SE 7) — подробное руководство по методам класса String в Java API.
  3. Pattern (Java Platform SE 7) — официальное руководство по регулярным выражениям в Java.
  4. StringUtils (Apache Commons Lang 3.14.0 API) — обзор универсальных инструментов из Apache Commons StringUtils.
  5. Регулярные выражения в Java – Tutorial — детальное руководство по регулярным выражениям в Java.