Explain Codes LogoExplain Codes Logo

Iterating through a list in reverse order in java

java
list-iteration
reverse-order
iterators
Anton ShumikhinbyAnton Shumikhin·Oct 4, 2024
TLDR

A swift way to reverse-iterate a List in Java is by initializing a ListIterator at the end of the list with list.listIterator(list.size()). Your subsequent loop can use hasPrevious() and previous().

List<String> list = Arrays.asList("a", "b", "c"); ListIterator<String> it = list.listIterator(list.size()); while(it.hasPrevious()) { System.out.println(it.previous()); // Hey "c", "b", "a", it's your turn! }

This approach is universally applicable to any List type, including ArrayList, LinkedList, and others.

Leveling up with ListIterator for cleaner code

By utilizing ListIterator, your code gains a new superpower — readability. By avoiding explicit indices, it's easier for other devs (and future you) to comprehend your mad programming skills.

Taking a tour of alternate reverse iteration strategies

Keeping it simple with Collections.reverse

When you need a lightweight alternative or ListIterator feels like swinging a sledgehammer on a thumbtack, Collections.reverse() can flip your List order, enabling a standard for-each loop to stroll backwards.

List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c")); Collections.reverse(list); for(String item : list) { System.out.println(item); // "c", "b", "a" walk into a loop... }

Crafting a custom reverse iterator

Crafting a custom reverse Iterator allows omniscient control and encapsulation of the reverse logic. Plus, it gives you bragging rights in the next dev standing.

public class ReverseIterator<T> implements Iterator<T> { private final List<T> list; private int position; public ReverseIterator(List<T> list) { this.list = list; this.position = list.size() - 1; // Pulling a Benjamin Button! } @Override public boolean hasNext() { return position >= 0; // The Iterator version of "Are we there yet?" } @Override public T next() { return list.get(position--); // Like turning back time...one element at a time. } }

Bi-directional adventures with Deque

Your friendly neighborhood Deque offers descendingIterator(), which makes traversing your list in the opposite direction a breezy walk in the park.

Deque<String> deque = new ArrayDeque<>(Arrays.asList("a", "b", "c")); Iterator<String> iterator = deque.descendingIterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); // Take this, gravity! }

Some extra practical nuggets

Performance versatility between ArrayList and LinkedList

While the ListIterator plays nice with every kid in the block, remember that ArrayList and LinkedList play ball differently. Where ArrayList takes the fast lane with array indexing, LinkedList prefers a chill stroll through node traversal via descendingIterator().

Flexing LinkedList's built-in capabilities

Embrace the built-in descendingIterator() of LinkedList for smooth sailing in reverse iteration.

LinkedList<String> linkedList = new LinkedList<>(Arrays.asList("a", "b", "c")); Iterator<String> it = linkedList.descendingIterator(); while(it.hasNext()) { System.out.println(it.next()); // It's like moonwalking with data! }

Going Guava for an elegant alternative

When dependency is not your kryptonite, Google Guava has got your back with Lists.reverse(). It paints an immutable reverse landscape of your list.

List<String> guavaReversedList = Lists.reverse(list); guavaReversedList.forEach(System.out::println); // Guava love, coming right up!

Unnecessary list reversal? Not on my watch!

Pre-bake your logic to produce lists in reverse. You need not reverse what was never reversed. Such refactors lead to optimized runtime performance, preventing any facepalms during code reviews.