001package co.codewizards.cloudstore.core.collection; 002 003import static co.codewizards.cloudstore.core.util.Util.*; 004import static java.util.Objects.*; 005 006import java.lang.reflect.Array; 007import java.util.Collection; 008import java.util.Collections; 009import java.util.Iterator; 010import java.util.List; 011import java.util.ListIterator; 012 013/** 014 * View reversing a given {@link List}. 015 * <p> 016 * In contrast to {@link Collections#reverse(List)}, wrapping a {@code ReverseListView} around another 017 * {@link List} does not modify the wrapped {@link List}. It is fully backed by the original {@link List}, 018 * hence every write operation is written through and modifications to the underlying {@link List} are 019 * immediately visible. 020 * 021 * @author Marco หงุ่ยตระกูล-Schulze - marco at codewizards dot co 022 * 023 * @param <E> the element type. 024 */ 025public final class ReverseListView<E> implements List<E> { 026 private final List<E> list; 027 028 public ReverseListView(final List<E> list) { 029 this.list = requireNonNull(list, "list"); 030 } 031 032 @Override 033 public int size() { 034 return list.size(); 035 } 036 037 @Override 038 public boolean isEmpty() { 039 return list.isEmpty(); 040 } 041 042 @Override 043 public boolean contains(Object o) { 044 return list.contains(o); 045 } 046 047 @Override 048 public final Iterator<E> iterator() { 049 return listIterator(0); 050 } 051 052 @Override 053 public Object[] toArray() { 054 return toArray(new Object[size()]); 055 } 056 057 @SuppressWarnings("unchecked") 058 @Override 059 public <T> T[] toArray(T[] a) { 060 if (a.length < list.size()) 061 a = (T[]) Array.newInstance(a.getClass(), list.size()); 062 063 int index = -1; 064 for (final E e : this) 065 a[++index] = (T) e; 066 067 return a; 068 } 069 070 @Override 071 public boolean add(E e) { 072 list.add(0, e); 073 return true; 074 } 075 076 @Override 077 public boolean remove(Object o) { 078 return list.remove(o); 079 } 080 081 @Override 082 public boolean containsAll(Collection<?> c) { 083 return list.containsAll(c); 084 } 085 086 @Override 087 public boolean addAll(Collection<? extends E> c) { 088 if (c.isEmpty()) 089 return false; 090 091 for (E e : c) 092 add(e); 093 094 return true; 095 } 096 097 @Override 098 public boolean addAll(int index, Collection<? extends E> c) { 099 if (c.isEmpty()) 100 return false; 101 102 for (E e : c) 103 add(index++, e); 104 105 return true; 106 } 107 108 @Override 109 public boolean removeAll(Collection<?> c) { 110 return list.removeAll(c); 111 } 112 113 @Override 114 public boolean retainAll(Collection<?> c) { 115 return list.retainAll(c); 116 } 117 118 @Override 119 public void clear() { 120 list.clear(); 121 } 122 123 @Override 124 public boolean equals(final Object o) { 125 if (o == this) 126 return true; 127 128 if (! (o instanceof List)) 129 return false; 130 131 final List<?> other = (List<?>) o; 132 if (this.size() != other.size()) 133 return false; 134 135 final Iterator<E> thisIterator = this.iterator(); 136 final Iterator<?> otherIterator = other.iterator(); 137 while (thisIterator.hasNext() && otherIterator.hasNext()) { 138 final E thisElement = thisIterator.next(); 139 final Object otherElement = otherIterator.next(); 140 if (! equal(thisElement, otherElement)) 141 return false; 142 } 143 return thisIterator.hasNext() == otherIterator.hasNext(); 144 } 145 146 @Override 147 public int hashCode() { 148 int hashCode = 1; 149 for (E e : this) 150 hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); 151 return hashCode; 152 } 153 154 @Override 155 public E get(int index) { 156 return list.get(translateIndex(index)); 157 } 158 159 @Override 160 public E set(int index, E element) { 161 return list.set(translateIndex(index), element); 162 } 163 164 @Override 165 public void add(int index, E element) { 166 list.add(translateIndex(index), element); 167 } 168 169 private int translateIndex(final int index) { 170 return list.size() - index - 1; 171 } 172 173 @Override 174 public E remove(int index) { 175 return list.remove(translateIndex(index)); 176 } 177 178 @Override 179 public int indexOf(Object o) { 180 return translateIndex(list.lastIndexOf(o)); 181 } 182 183 @Override 184 public int lastIndexOf(Object o) { 185 return translateIndex(list.indexOf(o)); 186 } 187 188 @Override 189 public final ListIterator<E> listIterator() { 190 return listIterator(0); 191 } 192 193 @Override 194 public final ListIterator<E> listIterator(final int index) { 195 return new ListIterator<E>() { 196 private final ListIterator<E> listIter = list.listIterator(translateIndex(index) + 1); 197 198 @Override public boolean hasNext() { return listIter.hasPrevious(); } 199 @Override public E next() { return listIter.previous(); } 200 @Override public void remove() { listIter.remove(); } 201 @Override public boolean hasPrevious() { return listIter.hasNext(); } 202 @Override public E previous() { return listIter.next(); } 203 @Override public int nextIndex() { return listIter.previousIndex(); } 204 @Override public int previousIndex() { return listIter.nextIndex(); } 205 @Override public void set(E e) { listIter.set(e); } 206 207 @Override 208 public void add(E e) { 209 listIter.add(e); 210 211 // According to javadoc, next() must be unaffected by add(...), while previous() must return the added element. 212 // In order to comply with this contract, we must call this.next() (which is the delegate's previous()), now! 213 if (e != next()) 214 throw new IllegalStateException("WTF?!"); 215 } 216 }; 217 } 218 219 @Override 220 public List<E> subList(int fromIndex, int toIndex) { 221 return new ReverseListView<E>(list.subList(translateIndex(toIndex), translateIndex(fromIndex))); 222 } 223 224 @Override 225 public String toString() { 226 final Iterator<E> it = iterator(); 227 if (! it.hasNext()) 228 return "[]"; 229 230 final StringBuilder sb = new StringBuilder(); 231 sb.append('['); 232 for (;;) { 233 final E e = it.next(); 234 sb.append(e == this || e == list ? "(this Collection)" : e); 235 if (! it.hasNext()) 236 return sb.append(']').toString(); 237 sb.append(',').append(' '); 238 } 239 } 240}