There are several uses for .IntStream.range
One is to use the values themselves:int
IntStream.range(start, end).filter(i -> isPrime(i))....
Another is to do something N times:
IntStream.range(0, N).forEach(this::doSomething);
Your case (1) is to create an array filled with a range:
int[] arr = IntStream.range(start, end).toArray();
You say this is "very slow" but, like other respondents, I suspect your benchmark methodology. For small arrays there is indeed more overhead with stream setup, but this should be so small as to be unnoticeable. For large arrays the overhead should be negligible, as filling a large array is dominated by memory bandwidth.
Sometimes you need to fill an existing array. You can do that this way:
int[] arr = new int[end - start];
IntStream.range(0, end - start).forEach(i -> arr[i] = i + start);
There's a utility method that can do this even more concisely:Arrays.setAll
int[] arr = new int[end - start];
Arrays.setAll(arr, i -> i + start);
There is also which can fill an existing array in parallel. Internally, it simply uses an and calls on it. This should provide a speedup for large array on a multicore system.Arrays.parallelSetAll
IntStream
parallel()
I've found that a fair number of my answers on Stack Overflow involve using . You can search for them using these search criteria in the search box:IntStream.range
user:1441122 IntStream.range
One application of I find particularly useful is to operate on elements of an array, where the array indexes as well as the array's values participate in the computation. There's a whole class of problems like this.IntStream.range
For example, suppose you want to find the locations of increasing runs of numbers within an array. The result is an array of indexes into the first array, where each index points to the start of a run.
To compute this, observe that a run starts at a location where the value is less than the previous value. (A run also starts at location 0). Thus:
int[] arr = { 1, 3, 5, 7, 9, 2, 4, 6, 3, 5, 0 };
int[] runs = IntStream.range(0, arr.length)
.filter(i -> i == 0 || arr[i-1] > arr[i])
.toArray();
System.out.println(Arrays.toString(runs));
[0, 5, 8, 10]
Of course, you could do this with a for-loop, but I find that using is preferable in many cases. For example, it's easy to store an unknown number of results into an array using , whereas with a for-loop you have to handle copying and resizing, which distracts from the core logic of the loop.IntStream
toArray()
Finally, it's much easier to run computations in parallel.IntStream.range