170

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.

Ron Tuffin
  • 53,859
  • 24
  • 66
  • 78
  • 8
    The point of the "for-each" loop is that you just need to perform an operation on each element, and order is not important. For-each could process the elements in completely random order, and it would still be doing what it was designed for. If you need to process the elements in a particular way, I would suggest doing it manually. – muusbolla Jul 08 '09 at 13:46
  • 1
    Java collections library. Not really anything to do with the language. Blame Josh Bloch. – Tom Hawtin - tackline Jul 08 '09 at 13:50
  • 9
    @muusbolla: But as a List is an _ordered_ collection, surely its order will be honoured, regardless? Therefore for-each will not process the elements of a List in a random order. – Lee Kowalkowski Mar 22 '11 at 14:56
  • 8
    @muusbolla that is not true. Maybe in the case of `Set` derived collections. `foreach` guarantees iteration in the order of the iterator returned from the `iterator()` method of the collection. http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html – robert Aug 13 '14 at 08:58
  • I want this build-in too, in Python we could write this `for row in rows[::-1]` to do reversing iteration. Why not in Java? – Zhou Haibo Mar 22 '21 at 12:29

15 Answers15

158

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);
}
Vsevolod Golovanov
  • 4,068
  • 3
  • 31
  • 65
Nat
  • 9,820
  • 3
  • 31
  • 33
  • 23
    That's basically what Google's Iterables.reverse does, yes :) – Jon Skeet Jul 08 '09 at 13:50
  • 10
    I know there is a 'rule' that we have to accept Jon's answer :) but.. I want to accept this one (even though they are essentially the same) because it does not require me to include another 3rd party library (even though some could argue that that reason breaks one of the prime advantages of OO - reusability). – Ron Tuffin Jul 08 '09 at 14:21
  • Small error: In public void remove(), there should not be a return statement, it should be just: i.remove(); – Jesper Aug 13 '09 at 09:43
  • 11
    Collections.reverse() does NOT return a reversed copy but acts on the List passed to it as a parameter. Like your solution with the iterator, though. Really elegant. – er4z0r May 09 '12 at 19:42
101

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.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Our codebase makes heavy use of the generified version of Commons Collections released by larvalabs (http://larvalabs.com/collections/). Looking through the SVN repo for Apache Commons, it's clear that most of the work in releasing a java 5 version of Commons Collections is done, they just haven't released it yet. – skaffman Jul 08 '09 at 13:44
  • I like it. If it weren't so useful, I'd call that a plug. – geowa4 Jul 08 '09 at 13:47
  • I wonder why Jakarta never bothered to update Apache Commons. – Uri Jul 08 '09 at 13:55
  • 3
    They have updated it, that's what I'm saying. They just haven't released it. – skaffman Jul 08 '09 at 13:56
  • 23
    Iterables.reverse has been deprecated, use Lists.reverse or ImmutableList.reverse instead. – Garrett Hall Oct 18 '11 at 14:54
  • it seems Guava (19.0) does not have any implementation of Reverse anymore. is there any other alternative for the Lists.Reverse? – AaA Jun 29 '16 at 07:45
  • @AaA: What makes you say that? https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/Lists.java#L823 – Jon Skeet Jun 29 '16 at 07:58
  • I downloaded guava from [here](http://central.maven.org/maven2/com/google/guava/guava/19.0/) and my code give me `cannot find symbol` with arrow under `reverse`. here is my code: `private final List MyClasses; public void aMethod() { for (Class2 MC1: com.google.common.collect.Lists.reverse(MyClasses)) { MC1.method(); } }` – AaA Jun 29 '16 at 08:27
  • @AaA: Well I've just downloaded the jar file and tried it myself, and it's fine for me. I can't tell what you're doing wrong - I suggest you ask a new question with a [mcve]. – Jon Skeet Jun 29 '16 at 08:32
  • Someone from my team included the [google-collections-1.0](http://central.maven.org/maven2/com/google/collections/google-collections/1.0/google-collections-1.0.jar) in project which has a different definition of `com.google.common.collect.Lists`. removing that library fixed the issue. – AaA Jun 29 '16 at 09:04
  • Further, you can use Guava's Lists.reverse to iterate arrays by combining with Arrays.asList (a non-copying List wrapper over the array) or, for primitive types, the various Guava asList methods such as e.g. Ints.asList (although in the latter case you'll end up wastefully boxing and unboxing each primitive). – laszlok May 10 '17 at 15:11
46

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.

Gopi Reddy
  • 469
  • 4
  • 2
  • 4
    This approach may be fine for array based lists (such as ArrayList) but it would be sub-optimal for Linked Lists as each get would have to traverse the list from beginning to end (or possibly end to beginning) for each get. It is better to use a smarter iterator as in Nat's solution (optimal for all implementations of List). – Chris May 20 '11 at 17:54
  • 1
    Further, it strays from the request in the OP which explicitly asks for the `for each` syntax – Paul W May 21 '11 at 02:51
  • better readability: `for (int i = stack.size(); i-- >0;) {` – j-hap Oct 29 '21 at 05:38
11

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
}
Jason Plank
  • 2,336
  • 5
  • 31
  • 40
Phillip Gibb
  • 523
  • 1
  • 6
  • 19
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.

Uri
  • 88,451
  • 51
  • 221
  • 321
3

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)
serv-inc
  • 35,772
  • 9
  • 166
  • 188
2

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);           
    }
}
Veger
  • 37,240
  • 11
  • 105
  • 116
Krishna
  • 158
  • 2
  • 7
2

A work Around :

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

Or with guava :

Lists.reverse(stringList).forEach(str -> ...);
EssaidiM
  • 7,924
  • 1
  • 18
  • 22
1

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.

casperOne
  • 73,706
  • 19
  • 184
  • 253
1

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

fospathi
  • 537
  • 1
  • 6
  • 7
Allan
  • 2,889
  • 2
  • 27
  • 38
1

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.

Owen
  • 22,247
  • 13
  • 42
  • 47
1

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
*///:~
qiwen li
  • 11
  • 2
  • why is the `int current = size() - 1` right? why not the `int current = this.size() - 1` or `int current = super.size() - 1` – qiwen li Mar 14 '17 at 11:18
1

Starting with the upcoming Java 21, the reversed() method can be used to return a reversed view on the list, which can then be iterated over using an enhanced for statement:

for (String string : stringList.reversed()) {
    //...do something
}
M. Justin
  • 14,487
  • 7
  • 91
  • 130
0

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"

ScottMichaud
  • 343
  • 3
  • 7
0

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
}
Hanamant Jadhav
  • 627
  • 7
  • 12