Создать бесконечный поток <Integer>, содержащий целые числа (0, 1, -1, 2, -2, 3, -3, ...) - PullRequest
6 голосов
/ 10 июля 2019

Я сейчас готовлюсь к экзамену и работаю над следующим заданием:

Создание бесконечного потока, содержащего целые числа (0, 1, -1, 2, -2, 3, -3, ...).

Следующий поток генерирует нормальный бесконечный поток:

Stream<Integer> infiniteStream = Stream.iterate(1, i -> i + 1);

Существует ли метод или лямбда-выражение, которые производят как положительные, так и отрицательные числа?

Ответы [ 4 ]

7 голосов
/ 10 июля 2019

Примерно так:

Stream<Integer> infiniteStream = Stream.iterate(1, i -> i > 0 ? -i : (-i + 1));

Или, если вы хотите начать с 0:

Stream<Integer> infiniteStream = Stream.iterate(0, i -> i > 0 ? -i : (-i + 1));

Конечно, это также можно сделать с помощью IntStream:

IntStream infiniteStream = IntStream.iterate(0, i -> i > 0 ? -i : (-i + 1));
3 голосов
/ 10 июля 2019

Я хочу предоставить альтернативу ответу Erans.

Поскольку вы уже знаете, как работает основной бесконечный поток, вы можете использовать для этого дополнительные потоковые операции, например flatMap:

    final Stream<Integer> eransAnswer = Stream.iterate(1, i -> i > 0 ? -i : (-i + 1));

    final Stream<Integer> alternative = Stream.iterate(1, i -> i + 1)
            .flatMap(i -> Stream.of(i, -i));

    System.out.println(eransAnswer.limit(6).collect(Collectors.toList()));
    System.out.println(alternative.limit(6).collect(Collectors.toList()));

Обратите внимание, что это работает, только если flatMap лениво оценивается. Я положил limit туда, чтобы я мог получить его в некотором результате (toList), но он также работает с limit после flatMap.

Иногда вместо добавления «сложности» в формулу генерирования может иметь смысл, а может и не иметь смысла разделять ее и использовать операции промежуточного потока. Если ваш мыслительный процесс заключается в том, что вы чередуете числа, используйте ответ Erans. Если вы скорее думаете, что для бесконечного потока натуральных чисел вы хотите продублировать каждое число его обратным, чем намерение более четко передается альтернативой.

РЕДАКТИРОВАТЬ: Для обработки нуля, вы можете сделать Stream.concat(Stream.of(0), alternative)

2 голосов
/ 11 июля 2019

Если вы присмотритесь к схеме ниже, это, вероятно, намного проще, чем вы думаете:

0  1   2    3    4    5

|  |   |    |    |    |

0  1  (-1)  2   (-2)  3

Теперь вы можете посмотреть на это так: если число равно даже , в результате этот индекс делится на два (и минус это);если число равно нечетное , в результате индекс делится на два плюс 1.

Вы можете определить, является ли число нечетным или четным, просто взглянув на последний бит: если оноявляется 1 => нечетным;если оно 0 => четное.И вы можете разделить число на два, сдвинув его вправо один раз, например:

IntStream.range(0, 10)
         .map(x -> (x & 1) == 0 ? -(x >> 1) : (x >> 1) + 1)
         .forEachOrdered(System.out::println);
1 голос
/ 10 июля 2019

Если вы хотите, чтобы отрицание привело к паре целых чисел и показало -1,1, -2,2, -3,3, .. вас и сделайте это.

IntStream.iterate(1, i -> i + 1).flatMap(a -> IntStream.of(-a, a));
IntStream.iterate(-1,i -> i < 0 ? -i: -i - 1);
...