Статьи
Утилиты Telegram YouTube Отзывы

Генерация N одинаковых элементов через Stream API

4 января 2018

Тэги: Collections, Java, Stream API.

Предположим, вы хотите сгенерировать N одинаковых элементов. Это очень легко сделать в Java при помощи Stream API. Рассмотрим следующий метод:

private List<String> repeatedValueGenerator(String text, int count) {
    return Stream.generate(() -> text)
            .limit(count)
            .collect(Collectors.toList());
}

Сначала стрим при помощи метода generate() создаёт бесконечный стрим (Stream), а потом мы его ограничиваем при помощи метода limit().

Например, для того, чтобы вывести на экран список из трех одинаковых строк с текстом «test», нужно вызвать его следующим образом:

System.out.println(repeatedValueGenerator("test", 3));

В результате получим:

[test, test, test]


Комментарии

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());

Добавить комментарий

×

devmark.ru