Re: Improved for each loop
Tom Anderson wrote:
Not being able to for-loop over an Iterator, as opposed to an Iterable,
is also incredibly frustrating. I start with something like this:
for (String s: someCollectionOfStrings) {
fooBarDoStuff();
doSomethingOnlyForTheLastElement(); // needs a guard
}
And then i [sic] realsie that i [sic] can't do that - i [sic] have to rewrite the loop as
a while loop. Like:
Iterator<String> it = someCollectionOfStrings.iterator();
while (it.hasNext()) {
s = it.next()) {
fooBarDoStuff();
if (it.hasNext()) doSomethingOnlyForTheLastElement();
}
Which feels much less cohesive and more clunky to me.
If you want to use a traditional three-part for loop, you have to do
something bonkers like:
String s;
for (Iterator<String> it = someCollectionOfStrings.iterator();
it.hasNext() && ((s = it.next()) != null);) {
fooBarDoStuff();
if (it.hasNext()) doSomethingOnlyForTheLastElement();
}
First of all, what you did isn't all that "bonkers"; you've just been spoiled
by the convenience of for-each over Iterables.
Second, under most circumstances you'd declare the String inside the loop, not
outside. That's what would match a hypothetical for-each over Iterators anyway:
for ( Iterator <String> it = someCollectionOfStrings.iterator();
it.hasNext(); // nullity should have been prevented on insert
)
{
String s = it.next();
doStuff( s );
}
That can be compressed if it's that simple:
for ( Iterator <String> it = someCollectionOfStrings.iterator();
it.hasNext(); // nullity should have been prevented on insert
doStuff( it.next() )
)
{
}
Finally, if you start with 'someCollectionOfStrings' in the first place, why
do you need an explicit Iterator at all?
for( String s : someCollectionOfStrings )
{
doStuff( s );
}
The whole point of the for-each syntax is to spare you from retrieving the
Iterator. If you're retrieving the Iterator, then you don't need for-each
anyway. Just use one of the other two for-loop constructs I just illustrated.
--
Lew