Reputation: 54668
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.
Upvotes: 175
Views: 170433
Reputation: 8352
A work Around :
List<String> reversed = new ArrayList<>(stringList);
Collections.reverse(reversed);
reversed.forEach(str -> ...);
Or with guava :
Lists.reverse(stringList).forEach(str -> ...);
Upvotes: 3
Reputation: 9951
One approach would be to reverse the whole list, but this would have O(n)
performance with respect to its size. Note that the commonly-used Collections.reverse
method actually reverses the original list in place, which may be an undesirable side-effect.
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);
}
As per this answer, Java 21 includes an efficient List.reversed()
method which does exactly what is requested.
Upvotes: 164
Reputation: 21
You can iterate through an array in reverse order using For-Each loop like below:
public class Main {
public static void main(String[] args) {
int arr[] = {2,3,1,4,7,6};
int i = arr.length-1;
for(int e: arr){
// do something
System.out.print(arr[i] + "\t");
i--;
}
}
}
Upvotes: 0
Reputation: 21347
Starting with 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
}
Upvotes: 3
Reputation: 38297
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)
Upvotes: 3
Reputation: 657
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
}
Upvotes: 0
Reputation: 343
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"
Upvotes: 0
Reputation: 11
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
*///:~
Upvotes: 1
Reputation: 1503529
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.)
Upvotes: 102
Reputation: 158
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);
}
}
Upvotes: 2
Reputation: 523
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
}
Upvotes: 11
Reputation: 479
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.
Upvotes: 47
Reputation: 89849
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.
Upvotes: 6
Reputation: 22907
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.
Upvotes: 1
Reputation: 74560
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.
Upvotes: 1