ctomek
ctomek

Reputation: 1796

Shortest concise readable syntax to iterate over consecutive numbers from given range

In groovy I can iterate through numbers using that simple syntax:

(1..10).each {
    do_domething it
}

What is the shortest syntax to do that in Java? I am now exploring streams and I came up with such an idea:

IntStream.range(0, 10)
         .forEach(do_domething());

It is even longer than the traditional way (below), but seems to be more concise.

for (int i = 0; i < 10; i++)
    do_domething()

I am just curious if there is shorter and readable way of doing it. I don't know everything about Java so I am just asking, probably there is no such thing, but I would like to make sure.

Upvotes: 0

Views: 463

Answers (5)

Peter Lawrey
Peter Lawrey

Reputation: 533700

If you want concise you can use a helper method.

public static void each(int start, int end, IntConsumer consumer) {
    IntStream.range(start, end).forEach(consumer);
}

and then you can write

import static java.lang.System.out;

each(0, 10, out::println);

If "each" is a bit verbose you could use a connector character like

public static void ⁀(int start, int end, IntConsumer consumer) {
    IntStream.range(start, end).forEach(consumer);
}

public static void main(String... args) {
    ⁀(0, 10, out::println);
}

prints

0
1
2
3
4
5
6
7
8
9

Upvotes: 1

hft
hft

Reputation: 1245

You can use the so-called "Facetious Arrow" operator (it looks like an arrow "-->") to write the loop slightly more briefly. [Pro Tip: It's not really an arrow]

for (int i=10;i-->0;)doSomething();

For example:

for (int i=10;i-->0;)System.out.println(i);

Prints:

9
8
7
6
5
4
3
2
1
0

Upvotes: 0

flakes
flakes

Reputation: 23654

You could create a helper function to create an array

public static int[] range(final int length){
    return IntStream.range(0, length).toArray();
}

Then using a foreach loop all you need to write is:

for(int i : range(10)) {
    do_domething();
}

Upvotes: 0

Jose Martinez
Jose Martinez

Reputation: 12022

There are some major differences between those two that do not make them drop in replacements of each other.

A return from a regular for-loop will return from your method, but for the stream/lambda version it returns from the lambda function. See below.

    for (int i = 0; i < 10; i++) {
        if (i == 5) {
            return;//returns from the whole method
        }
    }

    IntStream.range(0, 10).forEach((i -> {
        if (i == 5) {
            return; //returns only from the lambda
        }
    }));

Another major difference is how the two code blocks interact with variables. For lambdas to interact with variables that our outside its scope, they need to be final. So the stream/lambda code below won't compile.

    String x = "";

    for (int i = 0; i < 10; i++) {
        if (i == 5) {
            x = "5";
        }
    }

    IntStream.range(0, 10).forEach((i -> {
        if (i == 5) {
            x = "5"; //wont compile
        }
    }));

There might be other differences between the two. But for me that last one has caused problems that has lead me to continue using the regular for-loop.

Upvotes: 2

Paul Boddington
Paul Boddington

Reputation: 37655

If you need to use IntStream.range repeatedly in one class, you can reduce verbosity by using a static import:

import static java.util.stream.IntStream.range;

Then the syntax becomes

range(0, 10).forEach(...)

Beyond that, there's not much else I can suggest. In my view it is a bit ridiculous that we have to write for(int i = 0; i < n; i++) repeatedly, but at least it has the advantage of being instantly recognisable.

Upvotes: 2

Related Questions