Using IntStream.range instead of an ordinary for loop

Java 8 and Streams are really nice. They can even make look ordinary for loops much cooler. Assume the following snippet:

for (int i = 0; i < 10; i++) {
elements[i] = new MyModel(i);
}

This can also be written with the IntStream class.

IntStream.range(0, 10).forEach(i -> elements[i] = new MyModel(i));

I think the second statement looks much cooler.

Anyone knows if the old for loop is more efficient? I would assume IntStream is handled well enough be the Java compiler but did not check.

About Lars Vogel

Lars Vogel is the founder and CEO of the vogella GmbH and works as Eclipse and Android consultant, trainer and book author. He is a regular speaker at international conferences, He is the primary author of vogella.com. With more than one million visitors per month this website is one of the central sources for Java, Eclipse and Android programming information.
This entry was posted in Eclipse, Lars Vogel. Bookmark the permalink.

16 Responses to Using IntStream.range instead of an ordinary for loop

  1. Tom Schindl says:

    You should try to use lamdas in a side effect free (in your code you modify the elements array) manner


    MyModel[] elements =
    IntStream.range(1, 10).mapToObj(MyModel::new).collect(Collectors.toList()).toArray(new MyModel[0]);

  2. Dave W says:

    I’m more concerned with being able to understand the code then how cool it looks. The for loop is much easier to understand. It uses only Java language constructs and doesn’t involve any runtime class libraries or methods. The important piece (elements[i] = new MyModel(i);) stands out on its own and isn’t hidden by a number of static class references and method calls that have to be decoded in order to figure out what is happening. The IntStream approach generates unnecessary garbage and the method calls will introduce unnecessary overhead to the system.

  3. Bill Trautman says:

    Not sure which one is more efficient, but the first one is definitely easier to understand whats happening looking at the loop… As a professional developer that at times needs to modify other’s code I like it when the logic and behavior is clear at first reading.

  4. Andrey Loskutov says:

    … Looking on both examples I just would prefer the easy to understand for loop without any lambdas. The lambdas should be used where appropriate, and not just because “we can”.

  5. daddy says:

    I agree with Andrey – examples written by both Lars and Tom are just overly complicated and hard to read one-liners, which are doomed to be misunderstood without comments. Or maybe that’s just my old mind refusing new and shiny.

  6. Ralf Heydenreich says:

    Hi,
    I think a simple for loop is faster than the lambdas because they (the lambdas) have some overhead (which is hidden from programmer). I’ve just written a simple test and found out that the for loop is nearly twice as fast as the lambdas (tested with only 10 iterations).

    Greetz,
    R.

  7. Ralph says:

    I agree to Andrey’s comment. At least for the given example it obfuscates the code more than it helps :)

    However, the streams might be appropriate in other contexts…

  8. Ralf Heydenreich says:

    Hallo zusammen, irgendwie vermisse ich meinen Kommentar von gestern… War da was falsch dran?
    Grüße,
    R.

  9. Lars Vogel says:

    Thanks for all the comments. I think the question, which one is faster was not answered. We all agreed that we can read for loop better. :-)

  10. Lars Vogel says:

    Ah, sorry missed Ralph comments. Looks like the old for loop is actually faster. Thanks everyone.

  11. b0b says:

    Amusingly, the for statement on a single line is slightly shorter than the ‘cooler’ (and slower) version:

    for (int i = 0; i elements[i] = new MyModel(i));

  12. b0b says:

    Damn, defeated by formatting:

    for (int i = 0; i elements[i] = new MyModel(i));

  13. George says:

    Tom, You can simplify it a little bit by writing

    MyModel[] elements = IntStream.range(1, 10).mapToObj(MyModel::new).toArray(MyModel[]::new);

    I agree with the others that for this very simple example the for loop is slightly more readable, OTOH that can easily change, for example, if you need to create the MyModel instances (or just call some function) in parallel for some reason…

  14. Dave Moten says:

    I used JMH to do benchmarks on these two. 3 warmup iterations of 1s, 10 iterations of 5s each.

    I used this code below (setting elements of a 1000 element array).

    Results were for loop was 8% faster than IntStream.

    forLoop:
    Result: 1997958.679 ±(99.9%) 15934.716 ops/s [Average]
    Statistics: (min, avg, max) = (1971973.218, 1997958.679, 2009755.042), stdev = 10539.828
    Confidence interval (99.9%): [1982023.963, 2013893.395]

    intStreamLoop:
    Result: 1843151.604 ±(99.9%) 16150.256 ops/s [Average]
    Statistics: (min, avg, max) = (1821494.523, 1843151.604, 1859951.272), stdev = 10682.395
    Confidence interval (99.9%): [1827001.348, 1859301.860]


    private static int[] elements = new int[1000];

    @Benchmark
    public void forLoop() {
    for (int i = 0; i < 1000; i++)
    elements[i] = i;
    }

    @Benchmark
    public void intStreamLoop() {
    IntStream.range(0, 1000).forEach(i -> {
    elements[i] = i;
    });
    }

  15. Troy says:

    Late to the party, but anyway: the first version is not only far easier to understand, but definitely also easier to debug. Take a look at Perl and you see where “cool” coding is taking you: a gazillion different ways to code the same thing with fewer and fewer characters. People seem to forget that code does need a certain verbosity to be readable. We’re not machines.

  16. Roman Dawydkin says:

    Tom’s version can be shorter :)
    MyModel[] models = IntStream.range(1, 20).mapToObj(MyModel::new).toArray(MyModel[]::new);

Comments are closed.