255

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 already provides 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.

5
  • 1
    Can you build the list in the reverse order to begin with? Commented Oct 18, 2010 at 19:50
  • Yes it does - java.uitl.List.listIterator(int) download.oracle.com/javase/6/docs/api/java/util/… Commented Oct 18, 2010 at 19:59
  • 2
    If you visit this link to find the answer how to reverse(modify) the list, this is the answer: Collections.reverse(list) Commented Sep 22, 2018 at 5:24
  • 3
    List.reverse() is available since Java 21. Commented Apr 28, 2023 at 10:08
  • Be careful not to use Collections.reverse(List<?> list) in a return statement expecting List<?> because : The Collections.reverse method does not return a new list ; instead, it modifies the given list in place and returns void. As a result, you cannot use it directly in a return statement. Commented Jan 5 at 5:30

14 Answers 14

247

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());

If you are using a List and don't have access to clone() you can use subList():

List<?> shallowCopy = list.subList(0, list.size());
Collections.reverse(shallowCopy);
Sign up to request clarification or add additional context in comments.

8 Comments

clone() normally would create a copy of the list. Anyway, List#clone() also does not exist.
You are technically right, the List interface itself doesn't provide the clone() method. But ArrayList, LinkedList and Vector all do.
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).
Note that Collections.reverse returns void, so you would lose the clone reference. You need to assign the clone to a variable first, then sort it.
subList doesn't copy, it just provides a view on the underlying list, therefore reversing this view will reverse the underlying list.
|
241

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.

7 Comments

The problem is that Guava is a very large library. See the discussion: github.com/google/guava/issues/1954 and code.google.com/p/guava-libraries/issues/detail?id=605
@Filipe de Lima Brito: ProGuard is still the best solution for library size, though there are likely improvements we can make. In any case, I don't think library size is relevant in any way to this answer.
Yes, the library size isn’t relevant to this answer, but is relevant to be informed for the programmers (therefore, I commented)! Thank you very much for this great library and for your suggestion @ColinD!
@ColinD, yup, it was my mistake. A colleague added google-collections which also have same namespace and class (List) but without reverse method. removing it made guava available again.
Developers don't always have control over what libraries they can use, and adding a whole new library for something so simple seems like overkill--especially given that the problem can be solved with ListIterator.previous()
|
85

If i have understood correct then it is one line of code .It worked for me .

 Collections.reverse(yourList);

1 Comment

That is not a list view. That modifies the list.
46

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();
}

2 Comments

This is the best answer, since (1) it does not require a library, and (2) it does not modify the original list, as the OP requested
3) It doesn't require a copy of the list (though that may not be such a big issue, but, yeah, closest to a view)
14

SequencedCollection#reversed

Since Java 21 there is a new interface SequencedCollection (which is a superinteface for List). It has the method reversed() which provides a reverse-ordered view of a collection:

jshell> List.of(1, 2, 3, 4, 5).reversed()
$1 ==> [5, 4, 3, 2, 1]

See JEP 431 and video.

Comments

11

I use this:

public class ReversedView<E> extends AbstractList<E>{

    public static <E> List<E> of(List<E> list) {
        return new ReversedView<>(list);
    }

    private final List<E> backingList;

    private ReversedView(List<E> backingList){
        this.backingList = backingList;
    }

    @Override
    public E get(int i) {
        return backingList.get(backingList.size()-i-1);
    }

    @Override
    public int size() {
        return backingList.size();
    }

}

like this:

ReversedView.of(backingList) // is a fully-fledged generic (but read-only) list

Comments

8

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

1 Comment

If you didn't want to use built-in descndingIterator() method, it seems like using a ConcurrentLinkedDeque would be the best to reverse a very large list? Basically just copy from one deck to the new deck using poll then offer ? Sorta like just having a deck of cards and taking each off the top into a new pile, in order.
7

Collections.reverse(nums) ... It actually reverse the order of the elements. Below code should be much appreciated -

List<Integer> nums = new ArrayList<Integer>();
nums.add(61);
nums.add(42);
nums.add(83);
nums.add(94);
nums.add(15);
//Tosort the collections uncomment the below line
//Collections.sort(nums); 

Collections.reverse(nums);

System.out.println(nums);

Output: 15,94,83,42,61

2 Comments

You're just repeating the answer someone else wrote 6 years ago
...and not a view. this mutates the list.
4

Since Java 21 use List.reversed.

Returns a reverse-ordered view of this collection. The encounter order of elements in the returned view is the inverse of the encounter order of elements in this collection. The reverse ordering affects all order-sensitive operations, including those on the view collections of the returned view. If the collection implementation permits modifications to this view, the modifications "write through" to the underlying collection. Changes to the underlying collection might or might not be visible in this reversed view, depending upon the implementation.

So you have a reversed view of the original list.

Comments

3

I know this is an old post but today I was looking for something like this. In the end I wrote the code myself:

private List reverseList(List myList) {
    List invertedList = new ArrayList();
    for (int i = myList.size() - 1; i >= 0; i--) {
        invertedList.add(myList.get(i));
    }
    return invertedList;
}

Not recommended for long Lists, this is not optimized at all. It's kind of an easy solution for controlled scenarios (the Lists I handle have no more than 100 elements).

Hope it helps somebody.

2 Comments

Your code have a one problem - you can put any List to it, but it'll always return you ArrayList (as List). And what if I need LinkedList? It's better to modify myList, and return void.
Note that this is not really what I was asking for. I was asking for some sort of proxy/view, not a copy.
1

You can also invert the position when you request an object:

Object obj = list.get(list.size() - 1 - position);

Comments

1

For small sized list we can create LinkedList and then can make use of descending iterator as:

List<String> stringList = new ArrayList<>(Arrays.asList("One", "Two", "Three"));
stringList.stream().collect(Collectors.toCollection(LinkedList::new))
         .descendingIterator().
         forEachRemaining(System.out::println); // Three, Two, One
System.out.println(stringList); // One, Two, Three

Comments

0

UPDATE 2024.06.16:

After an awesome comment from Emmanuel Bourg, I took another look at the code and upgraded it to be modern-style null safe, and incorporating his excellent suggestion. The original code is captured below the last horizontal rule.

It's considerably more aligned with the latest versions of Java, i.e., exploiting null is a type-hole, mutating a method parameter is a type-hole code smell, and mutability being restricted to as small a block of code within a single method as possible to improve FP composability (as opposed to the weaker and error-prone OOP reusability).


For anyone on Java 21 or later, use List.reversed().

For anyone on Java 8 through Java 20 who...

  1. Wants to guard against null
  2. Does not want to modify the passed parameter, List<T> (a strong code smell)
  3. Wants to return an unmodifiable List<T>
  4. Does not want to use a third-party library like Guava
  5. Wants a function that follows the Java Collection API Stream<T>'s fluent calling style
  6. Wants to see modern style code (and to move away from the very C-like code from the late 1990s)
  7. Wants to move towards expressions (and to move away from statements)
  8. Wants to avoid reimplementing as much as possible (in this case, by calling the mutation-oriented imperative method, Collections.reverse(), already present in the Java Collections API)

...here's a useful solution I've generated:

/**
 * Returns a {@link Collections#unmodifiableList} with the contained instances in reverse order.
 *
 * @param list the list to copy from while reversing ({@code null} safe)
 * @param <T> the type of instances contained in the {@link list}
 * @return a {@link Collections#unmodifiableList} with the contained instances in reverse order
 */
public static <T> List<T> reverse(List<T> list) {
  return Optional.ofNullable(list)
      .filter(listNonNull ->
         !listNonNull.isEmpty())
      .map(listNonEmpty -> {
        if (listNonEmpty.size() == 1) {
          return Collections.unmodifiableList(listNonEmpty);
        }

        var listNonEmptyCopy = new ArrayList<>(listNonEmpty);
        Collections.reverse(listNonEmptyCopy);

        return Collections.unmodifiableList(listNonEmptyCopy);
      })
      .orElse(List.of());
}

Originally Posted Code that was updated above (DO NOT USE):

/**
 * Reverse the order of the instances returning an unmodifiable list.
 *
 * @param list the list to copy from while reversing
 * @param <T> the type of instances contained in the list
 * @return an unmodifiable list with the contained instances in reverse order
 */
public static <T> List<T> reverse(List<T> list) {
  if (list.size() > 1) {
    var size = list.size();

    return IntStream.range(0, size)
        .mapToObj(index -> list.get(size - 1 - index))
        .toList();
  } else if (list.size() == 1) {
    return list;
  }

  return List.of();
}

1 Comment

"Modern" syntax doesn't mean better. This can be done in 3 readable lines: List copy = new ArrayList(list); Collections.reverse(copy); copy = Collections.unmodifiableList(copy);
-2

You can also do this:

static ArrayList<String> reverseReturn(ArrayList<String> alist)
{
   if(alist==null || alist.isEmpty())
   { 
       return null;
   }

   ArrayList<String> rlist = new ArrayList<>(alist);

   Collections.reverse(rlist);
   return rlist;
}

2 Comments

That is not a list view. A view is the opposite of a copy.
The reverse list of an empty list is null??

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.