Can one do a for each loop in java in reverse order?

JavaReverseForeach

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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 - Java

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 - Java

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 - Java

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 - Java

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.

Solution 6 - Java

As of the comment: You should be able to use Apache Commons ReverseListIterator

Iterable<String> reverse 
    = new IteratorIterable(new ReverseListIterator(stringList));

for(String string: reverse ){
    //...do something
}

As @rogerdpack said, you need to wrap the ReverseListIterator as an Iterable.

As recommended by Roland Nordborg-Løvstad in the comments, you can simplify with Lambdas in current Java

Iterable<String> reverse = () -> new ReverseListIterator<>(stringList)

Solution 7 - Java

This may be an option. Hope there is a better way to start from last element than to while loop to the end.

public static void main(String[] args) {		
	List<String> a = new ArrayList<String>();
	a.add("1");a.add("2");a.add("3");a.add("4");a.add("5");
	
	ListIterator<String> aIter=a.listIterator();		
	while(aIter.hasNext()) aIter.next();
	
	for (;aIter.hasPrevious();)
	{
		String aVal = aIter.previous();
		System.out.println(aVal);			
	}
}

Solution 8 - Java

A work Around :

Collections.reverse(stringList).forEach(str -> ...);

Or with guava :

Lists.reverse(stringList).forEach(str -> ...);

Solution 9 - Java

Not without writing some custom code which will give you an enumerator which will reverse the elements for you.

You should be able to do it in Java by creating a custom implementation of Iterable which will return the elements in reverse order.

Then, you would instantiate the wrapper (or call the method, what-have-you) which would return the Iterable implementation which reverses the element in the for each loop.

Solution 10 - Java

You can use the Collections class to reverse the list then loop.

Solution 11 - Java

You'd need to reverse your collection if you want to use the for each syntax out of the box and go in reverse order.

Solution 12 - Java

All answers above only fulfill the requirement, either by wrapping another method or calling some foreign code outside;

Here is the solution copied from the Thinking in Java 4th edition, chapter 11.13.1 AdapterMethodIdiom;

Here is the code:

// The "Adapter Method" idiom allows you to use foreach
// with additional kinds of Iterables.
package holding;
import java.util.*;

@SuppressWarnings("serial")
class ReversibleArrayList<T> extends ArrayList<T> {
  public ReversibleArrayList(Collection<T> c) { super(c); }
  public Iterable<T> reversed() {
    return new Iterable<T>() {
      public Iterator<T> iterator() {
        return new Iterator<T>() {
          int current = size() - 1; //why this.size() or super.size() wrong?
          public boolean hasNext() { return current > -1; }
          public T next() { return get(current--); }
          public void remove() { // Not implemented
            throw new UnsupportedOperationException();
          }
        };
      }
    };
  }
}	

public class AdapterMethodIdiom {
  public static void main(String[] args) {
    ReversibleArrayList<String> ral =
      new ReversibleArrayList<String>(
        Arrays.asList("To be or not to be".split(" ")));
    // Grabs the ordinary iterator via iterator():
    for(String s : ral)
      System.out.print(s + " ");
    System.out.println();
    // Hand it the Iterable of your choice
    for(String s : ral.reversed())
      System.out.print(s + " ");
  }
} /* Output:
To be or not to be
be to not or be To
*///:~

Solution 13 - Java

Definitely a late answer to this question. One possibility is to use the ListIterator in a for loop. It's not as clean as colon-syntax, but it works.

List<String> exampleList = new ArrayList<>();
exampleList.add("One");
exampleList.add("Two");
exampleList.add("Three");

//Forward iteration
for (String currentString : exampleList) {
	System.out.println(currentString); 
}

//Reverse iteration
for (ListIterator<String> itr = exampleList.listIterator(exampleList.size()); itr.hasPrevious(); /*no-op*/ ) {
  	String currentString = itr.previous();
	System.out.println(currentString); 
}

Credit for the ListIterator syntax goes to ["Ways to iterate over a list in Java"][1]

[1]: https://stackoverflow.com/questions/18410035/ways-to-iterate-over-a-list-in-java "Ways to iterate over a list in Java"

Solution 14 - Java

E.g.

Integer[][] a = {
				{ 1, 2, 3 }, 
				{ 4, 5, 6 }, 
				{ 9, 8, 9 }, 
				};

List<List<Integer>> arr = Arrays.stream(a)
                .map(Arrays::asList)
                .collect(Collectors.toList());

Reverse it now.

Collections.reverse(arr);
System.out.println("Reverse Array" + arr);
for (List<Integer> obj : arr) {
	// TODO
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRon TuffinView Question on Stackoverflow
Solution 1 - JavaNatView Answer on Stackoverflow
Solution 2 - JavaJon SkeetView Answer on Stackoverflow
Solution 3 - JavaGopi ReddyView Answer on Stackoverflow
Solution 4 - JavaPhillip GibbView Answer on Stackoverflow
Solution 5 - JavaUriView Answer on Stackoverflow
Solution 6 - Javaserv-incView Answer on Stackoverflow
Solution 7 - JavaKrishnaView Answer on Stackoverflow
Solution 8 - JavaEssaidiMView Answer on Stackoverflow
Solution 9 - JavacasperOneView Answer on Stackoverflow
Solution 10 - JavaAllanView Answer on Stackoverflow
Solution 11 - JavaOwenView Answer on Stackoverflow
Solution 12 - Javaqiwen liView Answer on Stackoverflow
Solution 13 - JavaScottMichaudView Answer on Stackoverflow
Solution 14 - JavaHanamant JadhavView Answer on Stackoverflow