Can one do a for each loop in java in reverse order?
I need to run through a List in reverse order using Java.
So where this does it forwards:
for(String string: stringList){
//...do something
}
Is there some way to iterate the stringList in reverse order using the for each syntax?
For clarity: I know how to iterate a list in reverse order but would like to know (for curiosity's sake ) how to do it in the for each style.
Solution 1:
The Collections.reverse method actually returns a new list with the elements of the original list copied into it in reverse order, so this has O(n) performance with regards to the size of the original list.
As a more efficient solution, you could write a decorator that presents a reversed view of a List as an Iterable. The iterator returned by your decorator would use the ListIterator of the decorated list to walk over the elements in reverse order.
For example:
public class Reversed<T> implements Iterable<T> {
private final List<T> original;
public Reversed(List<T> original) {
this.original = original;
}
public Iterator<T> iterator() {
final ListIterator<T> i = original.listIterator(original.size());
return new Iterator<T>() {
public boolean hasNext() { return i.hasPrevious(); }
public T next() { return i.previous(); }
public void remove() { i.remove(); }
};
}
public static <T> Reversed<T> reversed(List<T> original) {
return new Reversed<T>(original);
}
}
And you would use it like:
import static Reversed.reversed;
...
List<String> someStrings = getSomeStrings();
for (String s : reversed(someStrings)) {
doSomethingWith(s);
}
Solution 2:
For a list, you could use the Google Guava Library:
for (String item : Lists.reverse(stringList))
{
// ...
}
Note that Lists.reverse
doesn't reverse the whole collection, or do anything like it - it just allows iteration and random access, in the reverse order. This is more efficient than reversing the collection first.
To reverse an arbitrary iterable, you'd have to read it all and then "replay" it backwards.
(If you're not already using it, I'd thoroughly recommend you have a look at the Guava. It's great stuff.)
Solution 3:
The List (unlike the Set) is an ordered collection and iterating over it does preserve the order by contract. I would have expected a Stack to iterate in the reverse order but unfortunately it doesn't. So the simplest solution I can think of is this:
for (int i = stack.size() - 1; i >= 0; i--) {
System.out.println(stack.get(i));
}
I realize that this is not a "for each" loop solution. I'd rather use the for loop than introducing a new library like the Google Collections.
Collections.reverse() also does the job but it updates the list as opposed to returning a copy in reverse order.
Solution 4:
This will mess with the original list and also needs to be called outside of the loop.
Also you don't want to perform a reverse every time you loop - would that be true if one of the Iterables.reverse ideas
was applied?
Collections.reverse(stringList);
for(String string: stringList){
//...do something
}
Solution 5:
AFAIK there isn't a standard "reverse_iterator" sort of thing in the standard library that supports the for-each syntax which is already a syntactic sugar they brought late into the language.
You could do something like for(Item element: myList.clone().reverse()) and pay the associated price.
This also seems fairly consistent with the apparent phenomenon of not giving you convenient ways to do expensive operations - since a list, by definition, could have O(N) random access complexity (you could implement the interface with a single-link), reverse iteration could end up being O(N^2). Of course, if you have an ArrayList, you don't pay that price.