String.contains: примеры (JAVA)
String.contains(CharSequence s): booleanОписание метода String.contains
Метод String.contains в Java проверяет, содержит ли строка указанную последовательность символов. Сигнатура метода: public boolean contains(CharSequence s). Возвращается булево значение: true, если указанная последовательность встречается в строке как подстрока, и false в противном случае.
Аргументы и поведение:
- Аргумент: объект, реализующий интерфейс
CharSequence. Часто этоString,StringBuilderилиStringBuffer. Передачаnullприводит кNullPointerException. - Сравнение: чувствительное к регистру и основано на точном совпадении последовательности char. Метод не выполняет привязки к локали.
- Пустая подстрока: вызов с пустой строкой (
"") всегда возвращаетtrueсогласно соглашению о подстроках. - Юникод и суррогатные пары: метод проверяет char-последовательность, а не логические code point; поиск суррогатных пар работает корректно при точном совпадении последовательностей UTF-16.
- Производительность: реализация вызывает
indexOf, сложность в худшем случае близка к O(n*m), где n - длина строки, m - длина искомой последовательности. - Потокобезопасность: класс
Stringнеизменяемый, поэтому вызов безопасен для чтения из разных потоков.
Возвращаемые значения:
true- если последовательность найдена.false- если последовательность не найдена.NullPointerException- при передачеnullв качестве аргумента.
Короткие примеры работы contains
Несколько базовых вариантов с выводом результата.
Пример 1. Простая проверка подстроки
String s = "hello world";
System.out.println(s.contains("world"));
true
Пример 2. Регистр имеет значение
String s = "Hello";
System.out.println(s.contains("hello"));
false
Пример 3. Пустая подстрока
String s = "abc";
System.out.println(s.contains(""));
true
Пример 4. CharSequence отличный от String
String base = "buffer test";
StringBuilder sb = new StringBuilder("buffer");
System.out.println(base.contains(sb));
true
Пример 5. Null в аргументе - исключение
String s = "x";
try {
System.out.println(s.contains(null));
} catch (Exception e) {
System.out.println(e.getClass().getSimpleName());
}
NullPointerException
Пример 6. Поиск с помощью регулярного выражения (contains не использует regex)
String s = "a1b2";
System.out.println(s.contains("\\d")); // ищется буквальное "\\d"
System.out.println(java.util.regex.Pattern.compile("\\d").matcher(s).find());
false true
Похожие методы в Java и их особенности
- indexOf(CharSequence): возвращает индекс первого вхождения или -1. Полезен при необходимости позиции подстроки или для проверки наличия (
indexOf(...) >= 0эквивалентcontains). - startsWith/endsWith: проверка начала или конца строки, быстрее при такой конкретной задаче.
- matches: проверка на соответствие регулярному выражению для всей строки, не подходит для простого contains без regex.
- Pattern/Matcher: поиск по регулярным выражениям с флагами (например, CASE_INSENSITIVE), предпочтительнее для сложных шаблонов или при многократных поисках (компиляция шаблона один раз).
- regionMatches: сравнение участка строки с другой строкой с опцией игнорирования регистра без создания новых строк в некоторых сценариях.
Аналоги в других языках и ключевые различия
- PHP (str_contains): с PHP 8.0 доступна функция
str_contains(string $haystack, string $needle): bool. По умолчанию чувствительна к регистру. Пример:var_dump(str_contains('hello','lo'));bool(true)
- JavaScript (includes / indexOf):
str.includes(sub)возвращает boolean, чувствителен к регистру. Альтернативаstr.indexOf(sub) !== -1.console.log('abc'.includes('b'));true
- Python ('in' / find): оператор
sub in sвозвращает булево. Методs.find(sub)возвращает индекс или -1.print('lo' in 'hello') print('hello'.find('x'))True -1
- SQL (LIKE, POSITION, INSTR): в SQL поиск подстроки выполняется через
LIKE '%sub%'илиPOSITION('sub' IN col). Регистрозависимость зависит от СУБД и колlation. - C# (String.Contains): есть перегрузка с
StringComparisonдля контроля регистра и культуры:str.Contains(sub, StringComparison.OrdinalIgnoreCase)доступна в новых версиях .NET. Пример:Console.WriteLine("Hello".Contains("he", StringComparison.OrdinalIgnoreCase));True
- Lua (string.find):
string.find(s, sub)возвращает позицию или nil. По умолчанию использует шаблоны Lua, для буквального поиска используетсяplain=true. - Go (strings.Contains): функция
strings.Contains(s, substr)возвращает bool, работает с байтами/руннами в соответствии с UTF-8, чувствительна к регистру.fmt.Println(strings.Contains("hello","ll"))true
- Kotlin (String.contains): есть перегрузка с параметром
ignoreCase: Boolean, что делает проверку регистронезависимой без дополнительной нормализации:str.contains(sub, ignoreCase = true).
Типичные ошибки при применении contains
- NullPointerException: передача
nullв метод.String s = "a"; System.out.println(s.contains(null));// Бросается исключение NullPointerException
- Ожидание регулярного поиска: метод не интерпретирует аргумент как regex. Частая ошибка - попытка найти цифровой символ через "\\d".
String s = "1"; System.out.println(s.contains("\\d"));false
- Путаница с регистром: проверка чувствительна к регистру. Для регистронезависимого сравнения создаются нормализованные строки или применяются Pattern/regionMatches.
System.out.println("Test".contains("t"));false
- Производительность: многократные вызовы с компиляцией regex в цикле или создание вспомогательных строк в горячих путях может замедлить приложение. Предпочтительнее компилировать
Patternодин раз при необходимости сложного поиска. - Путаница с массивами и коллекциями:
containsу строки проверяет подстроку, а не элемент в массиве. Закомментированные попытки использовать его для проверки наличия объекта в массиве приводят к логическим ошибкам.
Изменения и история метода
Метод String.contains(CharSequence) введён в Java 5 (JDK 1.5). С тех пор его поведение оставалось стабильным и не претерпевало существенных изменений в следующих релизах. В более поздних релизах платформа получила другие пригодные для поиска инструменты (новые методы в String, улучшения в API Pattern и классы для нормализации Unicode), однако сама реализация contains осталась прежней.
Расширенные и редкие сценарии использования
Подбор нескольких нестандартных примеров с комментариями.
Пример 1. Поиск без учета регистра с минимальными аллокациями через Pattern
String text = "Пример Текст";
java.util.regex.Pattern p = java.util.regex.Pattern.compile(java.util.regex.Pattern.quote("пример"), java.util.regex.Pattern.CASE_INSENSITIVE | java.util.regex.Pattern.UNICODE_CASE);
System.out.println(p.matcher(text).find());
true
Комментарий: компиляция шаблона один раз выгодна при многократных проверках.
Пример 2. Игнорирование диакритики через нормализацию
String a = "café";
String b = "cafe";
String na = java.text.Normalizer.normalize(a, java.text.Normalizer.Form.NFD).replaceAll("\\p{M}+", "");
String nb = java.text.Normalizer.normalize(b, java.text.Normalizer.Form.NFD).replaceAll("\\p{M}+", "");
System.out.println(na.contains(nb));
true
Комментарий: нормализация удаляет диакритические метки и позволяет сравнивать текст, независимо от способа кодирования символов.
Пример 3. Поиск emoji с учетом суррогатных пар
String s = "A \uD83D\uDE00 B"; // смайл в виде суррогатной пары
String emoji = new StringBuilder().appendCodePoint(0x1F600).toString();
System.out.println(s.contains(emoji));
true
Комментарий: создание строки из code point обеспечивает корректное представление суррогатной пары.
Пример 4. Фильтрация коллекции с contains
java.util.List list = java.util.Arrays.asList("alpha","beta","gamma");
list.stream().filter(s -> s.contains("a")).forEach(System.out::println);
alpha gamma beta
Комментарий: стрим использует лямбда-выражение; порядок вывода соответствует исходной коллекции.
Пример 5. Быстрая проверка наличия подстроки с индексом
String s = "search in a long text";
// contains вызывает indexOf внутри, но явный indexOf пригоден, когда нужна позиция
int pos = s.indexOf("long");
System.out.println(pos >= 0 ? ("found at " + pos) : "not found");
found at 12
Комментарий: indexOf возвращает позицию, что бывает необходимо для дальнейшей обработки.