Explain Codes LogoExplain Codes Logo

How to get a reversed list view on a list in Java?

java
list-reversal
guava-library
list-iterator
Alex KataevbyAlex Kataev·Oct 8, 2024
TLDR
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); // Just an average list. Nothing to see here. List<Integer> reversed = new ArrayList<>(list); // A copycat list. Or is it? Collections.reverse(reversed); // And... Presto! reversed is now living up to its name

Call Collections.reverse() on a fresh ArrayList that's a carbon copy of your original list. This act of magical inversion goes down in the new list, leaving the original list's order untouched. Hold on, though. Immutable and real-time reversed views are a different breed, and need specialized techniques, like using ListIterator backwards or harnessing Java 8's Streams.

Detailed solutions to reversing lists

Get by with a little help from Guava

Guava's Lists.reverse(List) is as smooth as you can get for serving up a reversed list view:

List<Integer> originalList = Arrays.asList(1, 2, 3, 4, 5); // Still that same old list. List<Integer> reversedView = Lists.reverse(originalList); // Now THIS is a different perspective!

The plot twist? This method delivers a reversed list that's in sync with any updates to the originalList, without messing with its contents. It's like having a mirror image that changes as you do, giving you a constant reversed perspective.

Reverse iteration without needing plastic surgery

Sometimes, you just need to walk backwards through a list, without causing any disruption. For those leisurely strolls, call upon List.listIterator(int index):

ListIterator<Integer> iterator = list.listIterator(list.size()); while(iterator.hasPrevious()) { // Walk down memory lane Integer element = iterator.previous(); // Trip on the rogue Lego, i.e., process element }

This nifty trick allows us to walk backwards through our memories, ahem, I mean list, without needing a separate iterator or a list overhaul.

Look, don't touch: Read-only reversed view with ReversedView

Needing a reversed list view but terrified to touch the list? Breathe easy with a custom implementation of ReversedView that kindly extends AbstractList:

class ReversedView<E> extends AbstractList<E> { // Your friendly neighborhood list private final List<E> original; ReversedView(List<E> original) { // Construction zone this.original = original; } @Override public E get(int index) { // Giving you what you asked for, but in reverse return original.get(size() - 1 - index); } @Override public int size() { // Size matters return original.size(); } }

Just like LinkedList's descendingIterator(), this efficient approach provides read-only reversed view.

Reversing lists: best practices and what not to do

Choose your reversing method wisely

No two reversed list view methods are created the same.

  • Do you want the original list to proudly stand its ground?
  • Do you require your reversed list to be in real-time sync?
  • Is your reversed list aspiring to be mutable or immutable?
  • Are you dealing with a dauntingly large list?

All these intimate details about your list need to be considered when you select your reversing strategy.

Performance first

If you're only in it for the iteration, save resources by not replicating the list. Give ListIterator a chance to do the heavy-lifting. But if you demand a new list that can party hard (be passed around and modified), then Collections.reverse() on a copied list is ready to serve.

Safe coding is immutable and thread-safe

If your reversed list must never change, look no further than Guava's solution. For compliant coding in multi-thread environments, don't forget to ensure thread-safety when refreshing the original list.

When to use reversed list techniques

Real-time mutable list views

If you need a moving, breathing "mirror image" of your list, Guava's Lists.reverse() is your magician. Especially useful if your UI elements need to keep in step with a collection's state.

Backward iterations for algorithms

If your algorithm requires elements in reverse order without having any rebellious intentions, use List.listIterator(int index) to walk back in time.

One-time reversed snapshot

When you need to capture a frozen moment of your list in reverse, Collections.reverse() on a new list is your instant Polaroid.

Finer points of list reversal

Avoiding a head-on collision

With traffic rules, and list reversal, not being careful can lead to chaos. Remember, Collections.reverse() is an invasive procedure for the list. Reconsider if the original order is precious.

Check your imports

Ensure you've imported the Guava library if your heart's set on using Lists.reverse().

Custom reversed view: When to go there

Creating ReversedView is like building your own house: overkill for short stays but ideal for ones seeking performance benefits or custom behaviors in a large list.