Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Length of an infinite IntStream?

I have created an randomIntStream by this:

 final static PrimitiveIterator.OfInt startValue = new Random().ints(0, 60).iterator();

The documentation says this stream is actually endless.

I want to understand what happens there in the backround.

ints(0,60) is generating an infinite stream of integers. If this is infinite, why my machine is not leaking any memory?

I wonder, how many numbers are actually really generated and if this implemenentation can cause an error at the point where the stream still ends? Or will this stream constantly filled with new integers on the fly and it really never ends therefore?

And if I already ask this question, what is the best practise right now to generate random numbers nowadays?

like image 655
Anna Klein Avatar asked Jul 18 '18 08:07

Anna Klein


People also ask

Can Java streams be of infinite size?

We can create an infinite stream of any custom type elements by passing a function of a Supplier interface to a generate() method on a Stream.

What is an IntStream?

An IntStream interface extends the BaseStream interface in Java 8. It is a sequence of primitive int-value elements and a specialized stream for manipulating int values. We can also use the IntStream interface to iterate the elements of a collection in lambda expressions and method references.

What is the difference between Stream and IntStream?

What is the difference between both? IntStream is a stream of primitive int values. Stream<Integer> is a stream of Integer objects.

What is IntStream range in Java?

IntStream range() method in Java The range() method in the IntStream class in Java is used to return a sequential ordered IntStream from startInclusive to endExclusive by an incremental step of 1. This includes the startInclusive as well.


4 Answers

The stream is infinite¹ so you can generate as many ints as you want without running out. It does not mean that it keeps generating them when you aren't asking for any.

How many numbers are actually generated depends on the code you write. Every time you retrieve a value from the iterator, a value is generated. None is generated in the background, so there's no "extra" memory being used.

¹ as far as your lifetime is concerned, see Eran's answer

like image 152
Kayaman Avatar answered Sep 28 '22 03:09

Kayaman


To be exact,

IntStream java.util.Random.ints(int randomNumberOrigin, int randomNumberBound) returns:

an effectively unlimited stream of pseudorandom int values, each conforming to the given origin (inclusive) and bound (exclusive).

This doesn't mean infinite. Looking at the Javadoc, you'll see an implementation note stating that it actually limits the returned IntStream to Long.MAX_VALUE elements:

Implementation Note:

This method is implemented to be equivalent to ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound).

Of course Long.MAX_VALUE is a very large number, and therefore the returned IntStream can be seen as "effectively" without limit. For example, if you consume 1000000 ints of that stream every second, it will take you about 292471 years to run out of elements.

That said, as mentioned by the other answers, that IntStream only generates as many numbers as are required by its consumer (i.e. the terminal operation that consumes the ints).

like image 35
Eran Avatar answered Sep 28 '22 04:09

Eran


Streams do not (in general1) store all of their elements in any kind of a data structure:

No storage. A stream is not a data structure that stores elements; instead, it conveys elements from a source such as a data structure, an array, a generator function, or an I/O channel, through a pipeline of computational operations.

Instead, each stream element is computed one-by-one each time the stream advances. In your example, each random int would actually be computed when you invoke startValue.nextInt().

So when we do e.g. new Random().ints(0,60), the fact that the stream is effectively infinite isn't a problem, because no random ints are actually computed until we perform some action that traverses the stream. Once we do traverse the stream, ints are only computed when we request them.

Here's a small example using Stream.generate (also an infinite stream) which shows this order of operations:

Stream.generate(() -> {
    System.out.println("generating...");
    return "hello!";
})
.limit(3)
.forEach(elem -> {
    System.out.println(elem);
});

The output of that code is:

generating...
hello!
generating...
hello!
generating...
hello!

Notice that our generator supplier is called once just before every call of our forEach consumer, and no more. If we didn't use limit(3), the program could run forever, but it wouldn't run out of memory.

If we did new Random().ints(0,60).forEach(...), it would work the same way. The stream would do random.nextInt(60) once before every call to the forEach consumer. The elements wouldn't be accumulated anywhere unless we used some action that required it, such as distinct() or a collector instead of forEach.


  1. Some streams probably use a data structure behind the scenes for temporary storage. For example, it's common to use a stack during tree traversal algorithms. Also, some streams such as those created using a Stream.Builder will require a data structure to put their elements in.
like image 30
Radiodef Avatar answered Sep 28 '22 04:09

Radiodef


As said by @Kayaman in his answer. The stream is infinite in the way that numbers can be generated forever. The point lies in the word can. It does only generate numbers if you really request them. It will not just generate X amount of numbers and then stores them somewhere (unless you tell it to do so).

So if you want to generate n (where n is an integer) random numbers. You can just call the overload of ints(0, 60), ints(n, 0, 60) on the stream returned by Random#ints():

new Random().ints(n, 0, 60)

Above will still not generate n random numbers, because it is an IntStream which is lazily executed. So when not using a terminal operation (e.g. collect() or forEach()) nothing really happens.

like image 36
Lino Avatar answered Sep 28 '22 04:09

Lino