4 января 2018
Тэги: Collections, Java, Stream API.
Предположим, вы хотите сгенерировать N одинаковых элементов. Это очень легко сделать в Java при помощи Stream API. Рассмотрим следующий метод:
Сначала стрим при помощи метода generate() создаёт бесконечный стрим (Stream), а потом мы ограничиваем его при помощи метода limit().
Например, для того, чтобы вывести на экран список из трех одинаковых строк с текстом «test», можно вызвать его так:
В результате получим:
Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, H2, Linux, Hibernate, Collections, Stream API, многопоточность, чат-боты, нейросети, файлы, devops, Docker, 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());