Skip to content

Instantly share code, notes, and snippets.

@FoxSamu
Last active July 21, 2022 13:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FoxSamu/f6f4b28a66cedd3a13c3a8c653813aef to your computer and use it in GitHub Desktop.
Save FoxSamu/f6f4b28a66cedd3a13c3a8c653813aef to your computer and use it in GitHub Desktop.
Java List reflecting another list in reverse order

A List implementation that reflects another list but in the reverse order. Usage: ReverseList.of(myList). The returned list implements RandomAccess if the provided list does so too (can have a slight performance boost).

Feel free to copy and edit this code however you like but please credit me.

package net.shadew.nbtedit.core.util;
import java.util.*;
public class ReverseList<E> implements List<E> {
private final List<E> delegate;
private ReverseList(List<E> delegate) {
this.delegate = delegate;
}
@Override
public int size() {
return delegate.size();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public boolean contains(Object o) {
return delegate.contains(o);
}
@Override
public Iterator<E> iterator() {
ListIterator<E> itr = delegate.listIterator(delegate.size());
return new Iterator<>() {
@Override
public boolean hasNext() {
return itr.hasPrevious();
}
@Override
public E next() {
return itr.previous();
}
@Override
public void remove() {
itr.remove();
}
};
}
private static <T> T[] reverseArray(T[] arr) {
int len1 = arr.length - 1;
int len2 = arr.length / 2;
for (int i = 0; i < len2; i++) {
int j = len1 - i;
T tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
return arr;
}
@Override
public Object[] toArray() {
return reverseArray(delegate.toArray());
}
@Override
@SuppressWarnings("SuspiciousToArrayCall")
public <T> T[] toArray(T[] a) {
return reverseArray(delegate.toArray(a));
}
@Override
public boolean add(E e) {
delegate.add(0, e);
return true;
}
@Override
public boolean remove(Object o) {
return delegate.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return delegate.containsAll(c);
}
@Override
@SuppressWarnings("unchecked")
public boolean addAll(Collection<? extends E> c) {
// Doing 'addAll' is generally faster than adding each element separately
// Especially on ArrayLists, which would otherwise do excessively many arraycopies (because it has to
// shift all elements rightwards for each element added, but with a bulk add it can immediately shift them
// into the right position with just one arraycopy)
Object[] arr = reverseArray(c.toArray());
return delegate.addAll(0, (List<E>) Arrays.asList(arr));
}
@Override
@SuppressWarnings("unchecked")
public boolean addAll(int index, Collection<? extends E> c) {
// See above method ^
Object[] arr = reverseArray(c.toArray());
return delegate.addAll(delegate.size() - index, (List<E>) Arrays.asList(arr));
}
@Override
public boolean removeAll(Collection<?> c) {
return delegate.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return delegate.retainAll(c);
}
@Override
public void clear() {
delegate.clear();
}
@Override
public E get(int index) {
return delegate.get(delegate.size() - 1 - index);
}
@Override
public E set(int index, E element) {
return delegate.set(delegate.size() - 1 - index, element);
}
@Override
public void add(int index, E element) {
delegate.add(delegate.size() - index, element);
}
@Override
public E remove(int index) {
return delegate.remove(delegate.size() - 1 - index);
}
@Override
@SuppressWarnings("SuspiciousMethodCalls")
public int indexOf(Object o) {
return delegate.size() - 1 - delegate.lastIndexOf(o);
}
@Override
@SuppressWarnings("SuspiciousMethodCalls")
public int lastIndexOf(Object o) {
return delegate.size() - 1 - delegate.indexOf(o);
}
@Override
public ListIterator<E> listIterator() {
return new ReverseListIterator(delegate.listIterator(delegate.size()));
}
@Override
public ListIterator<E> listIterator(int index) {
return new ReverseListIterator(delegate.listIterator(delegate.size() - index));
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
int s = delegate.size();
return new ReverseList<>(delegate.subList(s - toIndex, s - fromIndex));
}
private class ReverseListIterator implements ListIterator<E> {
private final ListIterator<E> itr;
private ReverseListIterator(ListIterator<E> itr) {
this.itr = itr;
}
@Override
public boolean hasNext() {
return itr.hasPrevious();
}
@Override
public E next() {
return itr.previous();
}
@Override
public boolean hasPrevious() {
return itr.hasNext();
}
@Override
public E previous() {
return itr.next();
}
@Override
public int nextIndex() {
return delegate.size() - 1 - itr.previousIndex();
}
@Override
public int previousIndex() {
return delegate.size() - 1 - itr.nextIndex();
}
@Override
public void remove() {
itr.remove();
}
@Override
public void set(E e) {
itr.set(e);
}
@Override
public void add(E e) {
itr.add(e);
}
}
// Make sure to provide RandomAccess if delegate list is also RandomAccess
private static class RAReverseList<E> extends ReverseList<E> implements RandomAccess {
private RAReverseList(List<E> delegate) {
super(delegate);
}
}
public static <E> ReverseList<E> of(List<E> list) {
if (list instanceof RandomAccess)
return new RAReverseList<>(list);
return new ReverseList<>(list);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment