bass3l
bass3l

Reputation: 111

Generate an infinite Stream<Integer> containing the integers (0, 1, -1, 2, -2, 3, -3, ...)

I am currently preparing for an exam and am working on the following task:

Generate an infinite Stream containing the integers (0, 1, -1, 2, -2, 3, -3, ...).

Following stream generate a normal infinite stream:

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

Is there a method or lambda expression that produces both positive and negative numbers?

Upvotes: 6

Views: 1040

Answers (4)

Eugene
Eugene

Reputation: 120978

If you look a bit closely to the scheme below, it's probably a lot easier than you might think:

0  1   2    3    4    5

|  |   |    |    |    |

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

Now, you can look at it this way: if the number is even, the result is that index divided by two (and minus that); if the number is odd, the result is that index divided by two plus 1.

You can tell if the number is odd or even, by simply looking at the last bit: if it is 1 => odd; if it is 0 => even. And you can divide a number by two by shifting it to the right once, as such:

IntStream.range(0, 10)
         .map(x -> (x & 1) == 0 ? -(x >> 1) : (x >> 1) + 1)
         .forEachOrdered(System.out::println);

Upvotes: 2

WJS
WJS

Reputation: 40072

If you want the negative to lead off the pair of integers and show -1,1,-2,2,-3,3,.. you and do this.

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

Upvotes: 1

sfiss
sfiss

Reputation: 2329

I want to provide an alternative to Erans answer.

Since you already know how the basic infinite stream works, you can use further stream operations like flatMap to build upon it:

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

Note that this only works if flatMap is lazily evaluated. I put the limit there so that I can collect it in some result (toList), but it also works with the limit after the flatMap.

Sometimes, instead of putting the "complexity" into your generating formula, it may or may not make sense to split it up and use intermediate stream operations. If your thought process is that you alternate numbers, use Erans answer. If you rather think that for the infinite stream of natural numbers, you want to duplicate each number with its inverse, than the intention is conveyed more clearly with the alternative.

EDIT: To handle the Zero, you can do Stream.concat(Stream.of(0), alternative)

Upvotes: 3

Eran
Eran

Reputation: 393956

Something like this:

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

Or, if you wish to start with 0:

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

Of course, this can also be done with IntStream:

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

Upvotes: 7

Related Questions