4 января 2018
Тэги: Collections, Java, Stream API.
Предположим, вы хотите сгенерировать N одинаковых элементов. Это очень легко сделать в Java при помощи Stream API. Рассмотрим следующий метод:
Сначала стрим при помощи метода generate() создаёт бесконечный стрим (Stream), а потом мы ограничиваем его при помощи метода limit().
Например, для того, чтобы вывести на экран список из трех одинаковых строк с текстом «test», можно вызвать его так:
В результате получим:
Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.
01.10.2022 11:16 Виктор
очень интересно…
а как поступить в том случае, если нужно сгенерировать несколько одинаковых цифр внутри строки? например, я генерирую шаблон:
public static final String LETTERS = "АВЕКМНОРСТУХ";
public static final String CAR_NUMBER_REGEX =
String.format("^[%s]\\d{3}[%s]{2}\\d{2,3}$", LETTERS, LETTERS);
И мне нужно чтобы вместо случайных \\d{3} – получить все 3 цифры одинаковые?
01.10.2022 12:44 Виктор
Предположим, я сгенерирую поток, поставив в условие соответствие с шаблоном CAR_NUMBER_REGEX, и потом, чтобы получить 3 одинаковых цифры, попытаюсь отфильтровать с помощью метода filter() и выставлю ограничение - к примеру 2000 случайных автомобильных номеров - следующим образом:
Stream.generate(() -> CAR_NUMBER_REGEX).filter().limit(2_000).collect(Collectors.toList());
Но как отфильтровать одинаковые цифры внутри шаблона? …Разбить шаблон на группы?
А как отфильтровать одинаковые цифры внутри группы?
02.10.2022 21:50 devmark
Виктор, какую задачу вы хотите решить? Если вы хотите выбрать 2000 случайных автомобильных номеров, то можно просто задать правило их прямого перебора в стриме (нечто вроде "AAA", "AAB", "AAE" и т.д.), затем перемешать, а затем выбрать 2000 первых.
21.11.2022 11:29 Виктор
Задача звучит так:
Реализуйте метод генерации «красивых» автомобильных номеров generateCoolNumbers() в классе CoolNumbers. Используйте следующие правила генерации номеров:
XYZ — различный набор из списка разрешенных букв, N — цифры, R — регион (от 01 до 199);
XNNNYZR — пример: A111BC197, У777HC66.
В госномерах автомобилей в РФ используются следующие буквы: А, В, Е, К, М, Н, О, Р, С, Т, У, Х.
21.11.2022 11:30 Виктор
Обычным способом эту задачу можно решить так:
public static List<String> generateCoolNumbers() {
final String[] carLetters = new String[] {"А", "В", "Е", "К", "М", "Н", "О", "Р", "С", "Т", "У", "Х"};
for (String letter : carLetters) {
for (int figure = 0; figure < 10; figure++) {
for (String letter_2 : carLetters) {
for (String letter_3 : carLetters) {
for (int m = 1; m <= 199; m++) {
String numberCar = String.format("%s%d%d%d%s%s%d", letter, figure, figure, figure, letter_2, letter_3, m);
coolNumbersList.add(numberCar);
}
}
}
}
}
return coolNumbersList;
}
Однако это решение имеет множество вложенных циклов. Что не есть хорошо.
21.11.2022 11:30 Виктор
Мне кажется эту задачу гораздо проще было бы решить через стримы?
В этом коде у меня возникла проблема: как отфильтровать номера с цифрами, чтобы все цифры в середине были одинаковыми?
public static final String LETTERS = "АВЕКМНОРСТУХ";
public static final String CAR_NUMBER_REGEX =
String.format("^[%s]\\d{3}[%s]{2}\\d{2,3}$", LETTERS, LETTERS);
public static List<String> generateCoolNumbers() {
return Stream.generate(() -> CAR_NUMBER_REGEX).limit(2_000).collect(Collectors.toList());
тогда мы смогли бы избавиться от множества вложенных циклов и решение станет намного изящнее
21.11.2022 11:45 devmark
Мне кажется тут в любом случае под капотом будет полный перебор всех значений. Можно сделать и на вложенных циклах. Главное тут не забить всю память. Для этого не сохранять лишние номера. А чтобы лишний раз не дёргать сборщик мусора, то вместо String итоговый номер складывать в массив символов. Тогда, кстати, даже не все значения на каждой итерации будут меняться. Ну и каждый номер проверяем на "красивость" и только красивые сохраняем. Мне кажется, такая реализация будет работать относительно быстро.
21.11.2022 11:55 devmark
А какой вообще критерий "красивости"? А то может задача ещё проще решается. Если красивый номер - это три одинаковых цифры, тогда перебор будет просто по 000, 111, 222, 333, ... т.е. в 1000 раз меньше итераций.
23.11.2022 21:51 Виктор
"...Если красивый номер - это три одинаковых цифры, тогда перебор будет просто по 000, 111, 222, 333, ... " именно это и имеется в виду. (!)
Можно ли создать с помощью filter() подобную фильтрацию внутри стрима?
public static List<String> generateCoolNumbers() {
return Stream.generate(() -> CAR_NUMBER_REGEX)
.filter(.......... ).limit(2_000).collect(Collectors.toList());