Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guava iterators, and iterating over a list within a list object

I have the following example code which consists of 3-nested for-loops.

for(Continent continent : continentList) 
{
    for(Country country : continent.getCountries())
    {
        for(City city : country.getCities())
        {
            //Do stuff with city objects
        }
    }
}

Is there any way to mimic this nested for-loop using Guava and iterators? I've been trying to find a suitable example without much luck, and I was wondering if someone could help me out? A coworker of mine mentioned using filters.

EDIT: Fixed tiny bug in example code

like image 795
GobiasKoffi Avatar asked Jan 15 '13 15:01

GobiasKoffi


People also ask

How do I loop through a list in streams?

A list provides quite precise control over where an element is to be inserted in the List. List interface provides a stream() method which gives a stream to iterate using forEach method. In forEach method, we can use the lambda expression to iterate over all elements.

Can we add element while iterating?

You can't modify a Collection while iterating over it using an Iterator , except for Iterator. remove() . This will work except when the list starts iteration empty, in which case there will be no previous element. If that's a problem, you'll have to maintain a flag of some sort to indicate this edge case.


1 Answers

As Peter Lawrey commented, this is almost certainly going to be simpler as nested loops. More over, the Guava documentation gives this warning:

Imperative code should be your default, your first choice as of Java 7. You should not use functional idioms unless you are absolutely sure of one of the following:

  • Use of functional idioms will result in net savings of lines of code for your entire project. Moving the definition of a function to another file, or a constant, does not help.
  • For efficiency, you need a lazily computed view of the transformed collection and cannot settle for an explicitly computed collection. Additionally, you have read and reread Effective Java, item 55, and besides following those instructions, you have actually done benchmarking to prove that this version is faster, and can cite numbers to prove it.

Please be sure, when using Guava's functional utilities, that the traditional imperative way of doing things isn't more readable. Try writing it out. Was that so bad? Was that more readable than the preposterously awkward functional approach you were about to try?

However, if you're insistent on ignoring advice, you could use something like this monstrosity (note I haven't actually tried to compile or run this):

FluentIterable.from(continentList)
    .transform(new Function<Continent, Void>() {
        public Void apply(Continent continent) {
            return FluentIterable.from(continent.getCountries())
                .transform(new Function<Country, Void>() {
                    public Void apply(Country country) {
                        return FluentIterable.from(country.getCities())
                            .transform(new Function<City, Void>() {
                                public Void apply(City city) {
                                    // do stuff with city object
                                    return null;
                                }
                            });
                    }
                });
        }
    });

Now ask yourself: Which would you want to maintain? Which is going to be the most efficient?

There are valid use-cases for Guava's functional idiom. Replacing Java for loops, even nested for loops, is not one of them.

like image 102
ig0774 Avatar answered Nov 12 '22 19:11

ig0774