Вступление
В этой статье мы рассмотрим, как проверить, начинается ли строка с другой строки в Java .
Это довольно распространенная задача в программировании, которая очень похожа на проверку того, содержит ли строка подстроку . Например, это может пригодиться, если мы хотим отфильтровать все слова из огромной выборки, начиная с определенной строки.
Однако эта проблема отличается от проверки того, содержит ли строка только определенную подстроку, и есть несколько способов сделать это как в Core Java, так и в Apache Commons :
- String.startsWith ()
- Stream.anyMatch ()
- String.indexOf ()
- Шаблон с регулярным выражением
- Использование цикла for
- StringUtils.indexOf ()
- StringUtils.startsWith ()
- StringUtils.startsWithAny ()
- StringUtils.startsWithIgnoreCase ()
Ядро Java
Начнем с решений, которые можно легко реализовать с помощью Core Java.
String.startsWith ()
Этот метод делает именно то, что нам нужно, и является наиболее
распространенным способом решения этой проблемы. Он возвращает boolean
, которое указывает, начинается ли строка с предоставленного ключевого
слова:
String string = "every end is a new beginning";
System.out.println(string.toLowerCase().startsWith("new".toLowerCase()));
System.out.println(string.toLowerCase().startsWith("EVERY".toLowerCase()));
System.out.println(string.toLowerCase().startsWith(""));
Запуск этих выходов:
false
true
true
Примечание. Если переданный параметр является пустой строкой,
результат всегда будет true
.
Конечно, этот метод чувствителен к регистру и всегда должен
использоваться в паре с toLowerCase()
или toUpperCase()
когда мы
просто ищем конкретное ключевое слово и не заботимся о том, совпадают ли
регистры.
Stream.anyMatch ()
Еще мы могли бы проверить, начинается ли строка с нескольких подстрок.
Скажем, у нас есть несколько стандартизованных префиксов - мы можем
использовать make Stream
из подстрок и запустить anyMatch()
для
строки, которую мы проверяем.
Давайте посмотрим, как это сделать:
String string = "every end is a new beginning";
System.out.println(Stream.of("every", "none").anyMatch(string::startsWith));
Здесь мы создали Stream
возможных подстрок и проверили, присутствует
ли какая-либо из них в начале данной строки, с помощью вызова ссылки на
метод для startsWith()
.
Этот код приводит к:
true
String.indexOf ()
Метод indexOf()
может быть весьма полезен при решении множества
проблем, связанных с подстроками, включая проверку того, начинается ли
строка с определенной.
Метод возвращает индекс первого вхождения подстроки в строке, если она
найдена, в противном случае -1
.
У него есть несколько перегруженных вариантов, из которых нам понадобится только один ниже, поскольку у других есть другие устройства:
public int indexOf(String str)
Если метод indexOf()
возвращает 0
, это означает, что наша строка
начинается с другой, которую мы указали в качестве параметра.
Например:
String string = "Just a sample String";
System.out.println(string.toLowerCase().indexOf("just".toLowerCase()));
System.out.println(string.toLowerCase().indexOf("String".toLowerCase()));
System.out.println(string.toLowerCase().indexOf("something else".toLowerCase()));
выведет:
0
14
-1
- Ответ, который мы ищем, находится в нашем первом примере, поскольку
он вернул
0
- именно то, что нам нужно, то есть наша строка начинается с заданного параметра. - Мы можем ясно видеть, что во втором примере
"String"
действительно находится в нашей String, но в позиции14
, а это не то, что мы искали. - Третий пример даже не содержится в нашей String и возвращает
-1
.
Используя информацию выше, мы можем накапливать логику в функции:
public static boolean startsWithSubstring(String text, String keyword) {
return text.toLowerCase().indexOf(keyword.toLowerCase()) == 0;
}
Шаблон с регулярным выражением и сопоставлением
Класс Pattern
- это скомпилированное представление регулярного
выражения. С помощью этого Pattern
мы можем затем сгенерировать
движок, который распознает указанное регулярное выражение - мы можем
сгенерировать Matcher
.
Мы будем использовать метод find()
в сочетании с start()
чтобы
проверить, Matcher
с заданной String:
public static boolean startsWithSubstring(String text, String keyword) {
String inputString = text.toLowerCase();
String subString = keyword.toLowerCase();
// We compile the regular expression to generate a Pattern object
Pattern pattern = Pattern.compile(subString);
// Then we generate an engine (Matcher) which can be used
// to recognize and match the regular expression it was
// generated from (in our case "this").
Matcher matcher = pattern.matcher(inputString);
// find() compares the assigned and compiled patterns, and will return a boolean value indicating if they match.
// That's where the start() method comes into play; it returns the index of the position
// where the two strings matched, or -1 if it's not found.
if (matcher.find()) {
return matcher.start() == 0;
}
return false;
}
Давайте протестируем этот метод:
System.out.println(startsWithSubstring(string, "every"));
Это приводит к:
true
Использование цикла for
Более низкоуровневым способом решения этой проблемы было бы использование цикла for.
Мы перебираем всю длину строки поиска, сравниваем первые
searchString.length()
и возвращаем true
если все совпадают.
Посмотрим, как все это работает в коде:
public static boolean startsWithSubstring(String text, String keyword) {
for (int i = 0; i < keyword.length(); i++) {
if (text.toLowerCase().charAt(i) != keyword.toLowerCase().charAt(i)) {
System.out.println("String doesn't start with " + "\"" + keyword + "\"");
return false;
} else if (i == keyword.length() - 1) {
System.out.println("String starts with " + "\"" + keyword + "\"");
return true;
}
}
return false;
}
Давайте протестируем этот метод:
String string = "Just a sample String";
System.out.println(startsWithSubstring(string, "just"));
System.out.println(startsWithSubstring(string, "String"));
System.out.println(startsWithSubstring(string, "something else"));
Это приводит к:
String starts with "just"
true
String doesn't start with "String"
false
String doesn't start with "something else"
false
По умолчанию, если бы мы не использовали toLowerCase()
для
выравнивания букв в самом методе, этот подход был бы чувствителен к
регистру .
Apache Commons
Библиотека Apache Commons предоставляет функциональные возможности, расширяющие базовую платформу Java Framework. Это одна из лучших сторонних библиотек, которая присутствует во многих современных Java-проектах.
Apache Commons предлагает StringUtils
, который содержит множество
методов, используемых для управления строками. Большинство из этих
методов очень похожи на методы, найденные в java.lang.String
.
Основное отличие состоит в том, что все методы в классе StringUtils
являются нулевыми .
Однако для этой задачи нам понадобится всего несколько методов из этого класса:
.indexOf()
.startsWith()
.startsWithIgnoreCase()
.
pom.xml
библиотеку Apache Commons в свой проект, добавив зависимость к
вашему файлу pom.xml, если вы используете Maven:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
Или добавив его в Gradle:
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.11'
StringUtils.indexOf ()
У этого метода есть несколько перегруженных вариантов, каждый из которых
возвращает int
указывающее индекс первого вхождения подстроки, или
-1
если подстрока вообще не появляется.
Мы остановимся на следующем варианте этого метода:
public static int indexOf(CharSequence seq, CharSequence searchSeq)
Этот метод принимает два String
/ CharSequence
.
Параметр seq
представляет строку, в которой мы будем искать
searchSeq
. Та же логика , как и раньше - если эта функция возвращает
0
, мы знаем , что наша строка начинается с заданной searchSeq
подстроки.
Также имейте в виду, что этот метод, как и его аналог, также
чувствителен к регистру , поэтому для достижения нечувствительности к
регистру необходимо .toLowerCase()
или .toUpperCase()
Использование этого метода очень похоже на использование indexOf()
из
java.lang.String
:
String string = "a simple string to search in";
System.out.println(StringUtils.indexOf(string.toLowerCase(), "a simple".toLowerCase()));
System.out.println(StringUtils.indexOf(string.toLowerCase(), "string".toLowerCase()));
System.out.println(StringUtils.indexOf(string.toLowerCase(), "something".toLowerCase()));
Это даст:
0
9
-1
Таким образом, мы можем использовать это как удобный метод:
public static boolean startsWithSubstring(String text, String keyword) {
return StringUtils.indexOf(text.toLowerCase(), keyword.toLowerCase()) == 0;
}
StringUtils.startsWith ()
Этот метод делает именно то, что вы ожидаете. Он также чувствителен к регистру, как и его предшественники, и принимает те же два параметра.
Он возвращает true
если text
начинается с keyword
, или false
если нет.
Сравнение двух null
значений приведет к true
:
String string = "a simple string to search in";
System.out.println(StringUtils.startsWith(string.toLowerCase(), "A SIMPLE"));
System.out.println(StringUtils.startsWith(string.toLowerCase(), "A SIMPLE".toLowerCase()));
System.out.println(StringUtils.startsWith(null, null));
Запуск этого выведет:
false
true
true
StringUtils.startsWithAny ()
startsWithAny()
не имеет аналога в java.lang.String
и является
уникальным для StringUtils
.
Однако это очень похоже на то, что мы сделали с anyMatch()
в потоке -
он проверяет, String
с любой из заданных подстрок, возвращая true
или false
.
Это также чувствительно к регистру:
String string = "a simple string to search in";
System.out.println(StringUtils.startsWithAny(string, "something", "a simple"));
System.out.println(StringUtils.startsWithAny(string, "something", "string"));
System.out.println(StringUtils.startsWithAny(string, "something", null));
System.out.println(StringUtils.startsWithAny(string, "something", ""));
Выполнение этого дает нам:
true
false
false
true
StringUtils.startsWithIgnoreCase ()
Поскольку вызов toLowerCase()
все время в Strings во время сравнения
может раздражать, вы также можете подать в суд на
startsWithIgnoreCase()
.
Как и метод startsWith()
из того же класса, он принимает два типа
Strings (или CharSequence
), а возвращаемое значение - true
или
false
зависимости от того, действительно ли текст начинается с
предоставленного ключевого слова:
String string = "a simple string to search in";
System.out.println(StringUtils.startsWithIgnoreCase(string, "something"));
System.out.println(StringUtils.startsWithIgnoreCase(string, "A SIMPLE"));
System.out.println(StringUtils.startsWithIgnoreCase(string, ""));
System.out.println(StringUtils.startsWithIgnoreCase(string, null));
Запуск этих выходов:
false
true
true
false
Заключение
В этой статье мы рассмотрели все различные методы проверки того,
String
с другой String
, как в ядре Java, так и с использованием
библиотеки Apache Commons.
В заключение, есть много разных способов выполнить эту задачу. На самом деле мы могли бы объединить любой из вышеперечисленных методов, чтобы найти индекс, с которого начинается подстрока, и оттуда проверить, где находится подстрока.
В большинстве случаев для решения этой проблемы достаточно просто
использовать методы startsWith()
startsWithIgnoreCase()
, а также
получить наиболее чистый и кратчайший код.