Для решения данной задачи стримы не слишком подходят, так как здесь необходимо хранить некоторое состояние при вычислении нового ключа в зависимости от выполнения условия.
При помощи Stream API можно построить промежуточную мапу "буква - список слов", а результат придется строить по некоторому заранее определённому алфавиту.
Также хотел заметить, что регулярное выражение разбиения строки на слова "\\W+"
предназначено для обработки слов, состоящим из букв английского алфавита, цифр и знака подчёркивания \w=[A-Za-z_0-9]; \W = [^\w]
. Слова на кириллице будут полностью отброшены, так как буквы будут входить в диапазон разделителей.
Вариант решения:
public static Map<String, List<String>> map(Stream<String> data, String alphabet, int min) {
Map<Character, List<String>> raw = data
// разбить по пробелам и символам пунктуации
.flatMap(s -> Arrays.stream(s.split("[\\p{Z}\\p{P}]+")))
// убрать пустые строки
.filter(w -> !w.isEmpty())
.collect(Collectors.groupingBy(
w -> Character.toUpperCase(w.charAt(0))
));
Map<String, List<String>> res = new LinkedHashMap<>();
List<String> merged = new ArrayList<>();
String key = "";
for (int i = 0, n = alphabet.length(); i < n; i++) {
Character c = alphabet.charAt(i);
List<String> words = raw.get(c);
if (null != words)
key += c; // включать только буквы имеющихся слов
merged.addAll(words);
if (words.size() >= min) {
// "улучшить" ключ
res.put(key.replaceAll("(\\p{L})(\\p{L}*)(\\p{L})", "$1-$3"), new ArrayList<>(merged));
merged.clear();
key = "";
}
}
if (!key.isEmpty())
res.put(key.replaceAll("(\\p{L})(\\p{L}*)(\\p{L})", "$1-$3"), new ArrayList<>(merged));
return res;
}
Тест
map(
Stream.of(
"Муха села на варенье, вот и все стихотворенье",
"Сова, открывай, медведь пришёл!",
"Прашу падергат и ждат атвета. Сава",
" Что значит я? \"Я\" бывают разные."
),
"АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ", 2
).forEach((k, v) -> System.out.println(k + ": " + v));
Результат:
А-В: [атвета, бывают, варенье, вот, все]
Ж-И: [ждат, значит, и, и]
М: [Муха, медведь]
Н-П: [на, открывай, пришёл, Прашу, падергат]
Р-С: [разные, села, стихотворенье, Сова, Сава]
Ч-Я: [Что, я, Я]
Если закомментировать проверку if (null != words)
, вид ключей изменится соответствующим образом:
А-В: [атвета, бывают, варенье, вот, все]
Г-И: [ждат, значит, и, и]
Й-М: [Муха, медведь]
Н-П: [на, открывай, пришёл, Прашу, падергат]
Р-С: [разные, села, стихотворенье, Сова, Сава]
Т-Я: [Что, я, Я]