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