Java: проверьте, содержит ли строка подстроку

Введение Проверка наличия подстрок внутри String - довольно распространенная задача в программировании. Например, иногда мы хотим разбить строку, если она содержит разделитель в точке. В других случаях мы хотим изменить поток, если строка содержит (или не имеет) определенную подстроку, которая может быть командой. В Java есть несколько способов сделать это, и большинство из них - это то, что вы ожидаете увидеть и на других языках программирования. Однако один подход, который является уникальным для Java, - это использование шаблона.

Вступление

Проверка наличия подстрок внутри String - довольно распространенная задача в программировании. Например, иногда мы хотим разбить строку, если она содержит разделитель в точке. В других случаях мы хотим изменить поток, если строка содержит (или не имеет) определенную подстроку, которая может быть командой.

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

В качестве альтернативы вы можете использовать Apache Commons и вспомогательный класс StringUtils , который предлагает для этой цели множество производных методов от основных методов.

Ядро Java

String.contains ()

Первый и самый важный способ проверить наличие подстроки - это метод .contains() Он предоставляется самим String и очень эффективен.

Метод принимает CharSequence и возвращает true если последовательность присутствует в String, для которого мы вызываем метод:

 String string = "Java"; 
 String substring = "va"; 
 
 System.out.println(string.contains(substring)); 

Выполнение этого даст:

 true 

Примечание. Метод .contains() чувствителен к регистру. Если бы мы попытались найти "Va" в нашей string , результат был бы false .

Часто, чтобы избежать этой проблемы, поскольку мы не ищем чувствительности к регистру, вы должны сопоставить регистр обеих строк перед проверкой:

 System.out.println(string.toLowerCase().contains(substring.toLowerCase())); 
 // OR 
 System.out.println(string.toUpperCase().contains(substring.toUpperCase())); 

String.indexOf ()

.indexOf() метод является немного более сырой , чем .contains() метод, но это тем не менее , основной механизм , который позволяет .contains() метод работы.

Он возвращает индекс первого вхождения подстроки в String и предлагает несколько конструкторов на выбор:

 indexOf(int ch) 
 indexOf(int ch, int fromIndex) 
 indexOf(String str) 
 indexOf(String str, int fromIndex) 

Мы можем либо искать одиночный символ со смещением или без него, либо искать строку со смещением или без него.

Метод вернет индекс первого вхождения, если он присутствует, и -1 если нет:

 String string = "Lorem ipsum dolor sit amet."; 
 
 // You can also use unicode for characters 
 System.out.println(string.indexOf('i')); 
 System.out.println(string.indexOf('i', 8)); 
 System.out.println(string.indexOf("dolor")); 
 System.out.println(string.indexOf("Lorem", 10)); 

Запуск этого кода даст:

 6 
 19 
 12 
 -1 
  • Первое вхождение i находится в слове ipsum , в 6 разрядах от начала последовательности символов.
  • Первое вхождение i со смещением 8 (т.е. начинается поиск в s от ipsum ) находится в sit слове, 19 мест с самого начала.
  • Первое появление String dolor - 12 разрядов от начала.
  • И, наконец, нет вхождения Lorem со смещением 10 .

В конечном счете, .contains() метод призывает .indexOf() метод для работы. Это делает .indexOf() своей сути даже более эффективным, чем аналог (хотя и в очень небольшом количестве), хотя у него есть немного другой вариант использования.

String.lastIndexOf ()

В отличие от .indexOf() , который возвращает первое вхождение, метод .lastIndexOf() возвращает индекс последнего вхождения символа или строки со смещением или без него:

 String string = "Lorem ipsum dolor sit amet."; 
 
 // You can also use unicode for characters 
 System.out.println(string.lastIndexOf('i')); 
 System.out.println(string.lastIndexOf('i', 8)); 
 System.out.println(string.lastIndexOf("dolor")); 
 System.out.println(string.lastIndexOf("Lorem", 10)); 

Запуск этого кода даст:

 19 
 6 
 12 
 0 

Некоторые могут быть немного удивлены результатами и скажут:

lastIndexOf('i', 8) должен был вернуть 19 поскольку это последнее вхождение символа после 8-го символа в строке

Стоит отметить, что при запуске .lastIndexOf() последовательность символов меняется на обратную. Подсчет начинается с последнего символа и идет к первому.

При этом - да. Ожидаемый результат - 6 , поскольку это последнее вхождение символа после пропуска 8 элементов с конца последовательности.

Шаблон с регулярным выражением и сопоставлением

Класс Pattern - это, по сути, скомпилированное представление регулярного выражения . Он используется вместе с Matcher для сопоставления последовательностей символов.

Этот класс работает, сначала компилируя шаблон. Затем мы назначаем другой шаблон Matcher , который использует метод .find() для сравнения назначенных и скомпилированных шаблонов.

Если они совпадают, метод .find() true . Если шаблоны не совпадают, метод возвращает false .

 Pattern pattern = Pattern.compile(".*" + "some" + ".*"); 
 
 Matcher matcher = pattern.matcher("Here is some pattern!"); 
 System.out.println(matcher.find()); 

Это даст:

 true 

Apache Commons

Из-за его полезности и распространенности в Java многие проекты имеют Apache Commons, включенные в путь к классам. Это отличная библиотека с множеством полезных функций, часто используемых в производстве, и проверка подстрок не исключение.

Apache Commons предлагает StringUtils со множеством вспомогательных методов для манипулирования строками, проверки нуля и т. Д. Для этой задачи мы можем использовать любой из .contains() , .indexOf() , .lastIndexOf() или .containsIgnoreCase() методы.

Если нет, включить его так же просто, как добавить зависимость к вашему pom.xml если вы используете Maven:

 <dependency> 
 <groupId>org.apache.commons</groupId> 
 <artifactId>commons-lang3</artifactId> 
 <version>{version}</version> 
 </dependency> 

Или добавив его через Gradle:

 compile group: 'org.apache.commons', name: 'commons-lang3', version: '{version}' 

StringUtils.contains ()

Метод .contains() довольно прост и очень похож на базовый подход Java.

Единственное отличие состоит в том, что мы не вызываем метод для проверяемой строки (поскольку он не наследует этот метод), а скорее передаем строку, в которой ищем, вместе со строкой, которую мы ищем:

 String string = "Checking for substrings within a String is a fairly common task in programming."; 
 
 System.out.println(StringUtils.contains(string, "common task")); 

Запуск этого кода даст:

 true 

Примечание. Этот метод чувствителен к регистру.

StringUtils.indexOf ()

Естественно, метод .indexOf() также работает очень похоже на базовый подход Java:

 String string = "Checking for substrings within a String is a fairly common task in programming."; 
 
 // Search for first occurrence of 'f' 
 System.out.println(StringUtils.indexOf(string, 'f')); 
 
 // Search for first occurrence of 'f', skipping the first 12 elements 
 System.out.println(StringUtils.indexOf(string, 'f', 12)); 
 
 // Search for the first occurrence of the "String" string 
 System.out.println(StringUtils.indexOf(string, "String")); 

Запуск этого кода даст:

 9 
 45 
 32 

StringUtils.indexOfAny ()

Метод .indexOfAny() принимает vararg символов вместо одного, что позволяет нам искать первое вхождение любого из переданных символов:

 String string = "Checking for substrings within a String is a fairly common task in programming."; 
 
 // Search for first occurrence of 'f' or 'n', whichever comes first 
 System.out.println(StringUtils.indexOfAny(string, ['f', 'n'])); 
 
 // Search for the first occurrence of "String" or "for", whichever comes first 
 System.out.println(StringUtils.indexOfAny(string, "String", "for")); 

Запуск этого кода даст:

 6 
 9 

StringUtils.indexOfAnyBut ()

Метод .indexOfAnyBut() ищет первое вхождение любого символа, которого нет в предоставленном наборе:

 String string = "Checking for substrings within a String is a fairly common task in programming."; 
 
 // Search for first character outside of the provided set 'C' and 'h' 
 System.out.println(StringUtils.indexOfAny(string, ['C', 'h'])); 
 
 // Search for first character outside of the provided set 'C' and 'h' 
 System.out.println(StringUtils.indexOfAny(string, ["Checking", "for"])); 

Запуск этого кода даст:

 2 
 14 

StringUtils.indexOfDifference ()

Метод .indexOfDifference() сравнивает два символьных массива и возвращает индекс первого различающегося символа:

 String s1 = "Hello World!" 
 String s2 = "Hello world!" 
 
 System.out.println(StringUtils.indexOfDifference(s1, s2)); 

Запуск этого кода даст:

 6 

StringUtils.indexOfIgnoreCase ()

Метод .indexOfIgnoreCase() вернет индекс первого вхождения символа в последовательности символов, игнорируя его регистр:

 String string = "Checking for substrings within a String is a fairly common task in programming." 
 
 System.out.println(StringUtils.indexOf(string, 'c')); 
 System.out.println(StringUtils.indexOfIgnoreCase(string, 'c')); 

Запуск этого кода даст:

 3 
 0 

StringUtils.lastIndexOf ()

И, наконец, метод .lastIndexOf() работает почти так же, как обычный базовый метод Java:

 String string = "Lorem ipsum dolor sit amet."; 
 
 // You can also use unicode for characters 
 System.out.println(StringUtils.lastIndexOf(string, 'i')); 
 System.out.println(StringUtils.lastIndexOf(string, 'i', 8)); 
 System.out.println(StringUtils.lastIndexOf(string, "dolor")); 
 System.out.println(StringUtils.lastIndexOf(string, "Lorem", 10)); 

Запуск этого кода даст:

 19 
 6 
 12 
 0 

StringUtils.containsIgnoreCase ()

Метод .containsIgnoreCase() проверяет, содержит ли String подстроку, игнорируя регистр:

 String string = "Checking for substrings within a String is a fairly common task in programming."; 
 
 System.out.println(StringUtils.containsIgnoreCase(string, "cOmMOn tAsK")); 

Запуск этого кода даст:

 true 

StringUtils.containsOnly ()

Метод .containsOnly() проверяет, содержит ли последовательность символов только указанные значения.

Это может немного ввести в заблуждение, поэтому другой способ выразиться

  • он проверяет, состоит ли последовательность символов только из указанных символов. Он принимает либо строку, либо последовательность символов:

    String string = “Hello World!” System.out.println(StringUtils.containsOnly(string, ‘HleWord!’)); System.out.println(StringUtils.containsOnly(string, “wrld”));

Выполнение этого даст:

 true 
 false 

"Hello World!" Строка действительно состоит только из символов 'HleWord!' последовательность.

Примечание. Не все символы из последовательности нужно использовать в string чтобы метод возвращал истину. Важно то, что string не содержит символа, которого нет в последовательности символов.

StringUtils.containsNone ()

Метод .containsNone() проверяет, содержит ли строка какие-либо «запрещенные» символы из набора. Если это так, false , и наоборот:

 String string = "Hello World!" 
 System.out.println(StringUtils.containsNone(string, 'xmt')); 
 System.out.println(StringUtils.containsNone(string, "wrld")); 

Выполнение этого кода дает:

 true 
 false 

StringUtils.containsAny ()

И, наконец, метод .containsAny() возвращает true если последовательность символов содержит любой из переданных параметров в виде последовательности символов или String:

 String string = "Hello World!" 
 System.out.println(StringUtils.containsAny(string, ['h', 'm'])); 
 System.out.println(StringUtils.containsAny(string, "hell")); 

Этот код даст:

 true 
 true 

Заключение

В заключение, есть много способов проверить подстроку в строке. Базового подхода Java будет достаточно в большинстве случаев, хотя, если вам нужно проверить более одного условия, Apache Commons реально сэкономит время.

Во многих случаях определение собственной логики для такого метода, как .indexOfAnyBut() было бы болезненным и просто излишним. Поскольку в настоящее время большинство проектов уже имеют Apache Commons в пути к классам, наиболее вероятно, что вы можете просто использовать методы, предоставляемые классом StringUtils

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus

Содержание