Please, stop writing so many “for loops” in Java!

In this blog post, I want to take you back to basics and talk about Java for loops. To be honest, I am writing this blog post partially for myself, as this is something that I am myself too often guilty of. Since Java 8, we don’t have to write so many for loops in Java! I hope this blog post will make your code nicer to read and quicker to write.

What do you need a for loop for?

Broadly speaking there are two categories of tasks performed by for loops:

  • Iterating over collections
  • Running algorithms

For algorithms, a for loop may be appropriate. Have a look at this algorithm checking if a number is a power of three:

double number = 81;
for(; number > 1; number /=3);
return number == 1;

For loop is an appropriate construct here. This is a very simple example and as you can imagine, things can get much trickier with more difficult algorithms.

For most developers, in their day to day work, this is a minority of cases. Most of the time, we use for loops to iterate over collections. Let’s look at some examples of that code.

Iterating over collections in Java

Let’s take a List<String> that contains some values.

List<String> heroes = new ArrayList<>();
heroes.add("SuperPerson");
heroes.add("WonderGirl");
heroes.add("LemurMan");
heroes.add("TimesTenDeveloper");
heroes.add("PandaFace");
heroes.add("CobraKid");
heroes.add("TShapedTeamMember");

There are many ways to iterate over it. Let’s start with the rather archaic Iterator approach:

Iterator<String> heroesIterator = heroes.iterator();
while (heroesIterator.hasNext()) {
    System.out.println(heroesIterator.next());
}

That looks really heavy weight. This kind of code gives Java its somewhat deserved reputation for verbosity.

Another try, this time with a classical indexed for loops:

for(int i = 0; i < heroes.size(); i++){
    System.out.println(heroes.get(i));
}

Well, this is a bit simpler to follow, but since Java 5 we have for each loop at our disposal:

for(String hero : heroes){
    System.out.println(hero);
}

This is where the most developers get stuck. This construct is so familiar and easy to follow, that most of us don’t bother to think about anything better. Java 8 is been available for a while though…

With Java 8 we can use a forEach function, making it very obvious what we are doing:

heroes.forEach(hero -> System.out.println(hero));

We can simplify it even further:

heroes.forEach(System.out::println);

I really like this, as it is very obvious that we are not running an algorithm with possibly a dynamic number of steps- we are just iterating over the elements of an array.

To be honest, I wish Java would allow us to also pass an index more easily with that style. Unfortunately, at the moment this is not possible:

//not legal Java!!!
heroes.forEach((hero , i) -> System.out.println(hero +" at "+i));

And if you want to keep using that style while accessing the index, you may need to resolve to less pretty:

IntStream.range(0, heroes.size())
        .forEach(i -> System.out.println(heroes.get(i) +" at "+i));

Where to go next? Use Java Streams

Once you stop writing so many for loops in Java and forEach becomes a second nature, you should look at Streams in Java.

With a similar syntax, you can, for example, easily choose all heroes beginning with a letter ‘T’:

heroes.stream().filter(hero -> hero.startsWith("T"))
        .forEach(System.out::println);

This gives you the famous “TimesTenDeveloper” and the “TShapedTeamMember”.

Summary

Stop writing so many for loops. Once you do, the Java 8 Streams will come as a natural step and your code will be easier to read and faster to write. What is not too like? Good luck!

Learn something new with the best programming courses available - sign up for a free trial with Pluralsight

2 thoughts on “Please, stop writing so many “for loops” in Java!”

  1. I think that for-each-loop syntax has many advantages over forEach.

    First it is buildin into the language and can be better optimized by the compiler.
    Second it provides an uniform and standard interface for iteration over any collection
    (forEach name is only a convention that may not be respected by all lib authors;
    they may choose to not provide forEach at all).

    Also with the advent of var keyword in Java 10 we may write:

    for (var hero : heroes) printHero(hero);
    // vs.
    heroes.forEach(this::printHero); // oh this ugly ‘this::’

    I can understand your sentiment agains for-each-loop because I saw
    many times how it is abused, people wrote:

    for (var h : heroes) {
    if (h.getName() == “Frodo”) return h;
    }
    return null;

    instead of:

    return heroes.stream()
    .filter(hero -> hero.getName() == “Frodo”)
    .findFirst().orElse(null); // or even better return Optional

    Indeed, since Java 8 using for loops to code logic that may be expressed
    by using streams is an antipattern.
    Yet for iterating over collections for-each-loop is as good as ever.

    1. Thanks 0xmarcin for your very thoughtful comment! I have to admit- I still write the standard “for each loop” quite often in the trivial cases and when coding for raw algorithmic speed. You provide a good example of the abuse/laziness that I am trying to educate against! Thanks for reading my blog.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.