简体   繁体   中英

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?

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

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)

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM