Найти количество вхождений подстроки в строку java stream api
Задали задачу на собеседовании: найти количество вхождений подстроки в строку с использованием java stream api.
Пример:
String str = "Multiple findme classes and nested " +
"static findme classes are supported, " +
"Printing unwanted or ill-formatted data " +
"to output will cause the test findmecases " +
"to failfindme";
String substr = "findme";
Результат:
4
Нужно решение на java stream api, ну или без него, если это совсем не оптимально.
Ответы (3 шт):
public static void main(String[] args) {
String str = "Multiple findme classes and nested " +
"static findme classes are supported, " +
"Printing unwanted or ill-formatted data " +
"to output will cause the test findmecases " +
"to failfindme";
String substr = "findme";
Long count = Arrays.stream(str.split(" "))
.filter(s -> s.contains(substr))
.count();
System.out.println(count);
}
Решение 1: используем фильтр.
String str = "Multiple findme classes and nested " +
"static findme classes are supported, " +
"Printing unwanted or ill-formatted data " +
"to output will cause the test findmecases " +
"to failfindme";
String substr = "findme";
long count =
// разделяем исходную строку по пробельным
// символам на массив слов и обходим его
Arrays.stream(str.split("\\s"))
// фильтруем стрим по словам,
// содержащим подстроку
.filter(word -> word.contains(substr))
// выводим количество слов
.count();
System.out.println(count); // 4
Такой алгоритм не будет работать для тех случаев, когда в каком-либо слове искомая подстрока встречается два раза или более.
Решение 2: должно работать во всех случаях, в т. ч. для двух и более вхождений подстроки в одно слово, также для цифр, спецсимволов и т. д.
long count =
// добавляем к исходной строке какой-либо
// символ и делим ее по подстроке.
// Обходим массив частей исходной строки
Arrays.stream((str + " ").split(substr))
// Считаем части
.count();
System.out.println(count - 1); // 4
Решение 3: упрощенный вариант, без стримов.
int count = (str + " ").split(substr).length;
System.out.println(count - 1); // 4
Стримом тоже можно решить эффективно (в данном случае без создания дополнительных массивов/коллекций и без использования регулярных выражений), хотя и не очень наглядно, по сути это завуалированный for.
(преимущества стрима будут видны если задание изменится и надо будет делать еще какие нибудь дополнительные операции)
long count = IntStream.iterate(
str.indexOf(substr), // начинаем с первого вхождения
i -> i != -1, // пока не получим негативный ответ
i -> str.indexOf(substr, i + 1)) // ищем следующее вхождение
.count(); // считаем вхождения
System.out.println(count);
Код будет работать и на больших строках, а также с пересекающимися подстроками, например
String str = "aaaaaaa";
String substr = "aa";
ЗЫ: Java9+