views:

134

answers:

5
+2  Q: 

java: reverse list

I want to have a reversed list view on a list (in a similar way than List#sublist provides a sublist view on a list). Is there some function which provides this functionality?

I don't want to make any sort of copy of the list nor modify the list.

It would be enough if I could get at least a reverse iterator on a list in this case though.


Also, I know how to implement this myself. I'm just asking if Java provides already something like this.

Demo implementation:

static <T> Iterable<T> iterableReverseList(final List<T> l) {
    return new Iterable<T>() {
        public Iterator<T> iterator() {
            return new Iterator<T>() {
                ListIterator<T> listIter = l.listIterator(l.size());                    
                public boolean hasNext() { return listIter.hasPrevious(); }
                public T next() { return listIter.previous(); }
                public void remove() { listIter.remove(); }                 
            };
        }
    };
}

I just have found out that some List implementations have descendingIterator() which is what I need. Though there is no general such implementation for List. Which is kind of strange because the implementation I have seen in LinkedList is general enough to work with any List.

+6  A: 

Guava provides this: Lists.reverse(List)

List<String> letters = ImmutableList.of("a", "b", "c");
List<String> reverseView = Lists.reverse(letters); 
System.out.println(reverseView); // [c, b, a]

Unlike Collections.reverse, this is purely a view... it doesn't alter the ordering of elements in the original list. Additionally, with an original list that is modifiable, changes to both the original list and the view are reflected in the other.

ColinD
+2  A: 

Its not exactly elegant, but if you use List.listIterator(int index) you can get a bi-directional ListIterator to the end of the list:

//Assume List<String> foo;
ListIterator li = foo.listIterator(foo.size());

while (li.hasPrevious()) {
   String curr = li.previous()
}
kkress
+2  A: 

java.util.Deque has descendingIterator() - if your List is a Deque, you can use that.

Bozho
+1  A: 

In Scala, you could just do:

scala> val xs = List(4, 5, 1, 9)
xs: List[Int] = List(4, 5, 1, 9)

scala> val view = xs.view.reverse
view: scala.collection.SeqView[Int,List[Int]] = SeqViewR(...)

scala> view foreach println
9
1
5
4

(copied from interactive shell)

Eric Grindt
A: 

Use the .clone() method on your List. It will return a shallow copy, meaning that it will contain pointers to the same objects, so you won't have to copy the list. Then just use Collections.

Ergo,

Collections.reverse(list.clone());
jcalvert
`clone()` normally would create a copy of the list. Anyway, `List#clone()` also does not exist.
Albert
You are technically right, the List interface itself doesn't provide the clone() method. But ArrayList, LinkedList and Vector all do.
jcalvert
Clone is a *shallow* copy of the list. It will not copy the members. But I think I understand where you're going with this now, in reference to a "view", as any structural change to the 'view' from subList() alters the original as well. I don't think you have any way to do what you want without creating a class as you did in your demo.
jcalvert
@jcalvert: I just looked up the implementation of `clone()`. It indeed does a full copy of the list (it only does not clone each single object in the list but that was never what I was talking about).
Albert