static final class IndexedList2 extends ArrayList {
final new HashMap index;
static int instances;
*() { ++instances; }
*(L x) {
this();
ensureCapacity(l(x));
addAll(x);
}
@Override
public A set(int i, A a) {
A prev = get(i);
if (prev != a) {
indexRemove(prev);
indexAdd(a);
super.set(i, a);
}
ret prev;
}
@Override
public void add(int i, A a) {
indexAdd(a);
super.add(i, a);
}
@Override
public bool add(A a) {
indexAdd(a);
ret super.add(a);
}
@Override
public A remove(int i) {
A a = get(i);
indexRemove(a);
super.remove(i);
ret a;
}
public bool remove(O a) {
int i = indexOf(a);
if (i < 0) false;
ret true with remove(i);
}
// speed up methods
@Override
protected void removeRange(int fromIndex, int toIndex) {
for (int i = fromIndex; i < toIndex; i++)
unindex(i);
super.removeRange(fromIndex, toIndex);
}
@Override
public int indexOf(O a) {
if (!contains(a)) ret -1;
ret super.indexOf(a);
}
@Override
public bool contains(O a) {
ret index.containsKey(a);
}
@Override
public void clear() {
index.clear();
super.clear();
}
@Override
public bool addAll(int i, Collection extends A> c) {
for (A a : c) indexAdd(a);
ret super.addAll(i, c);
}
// indexing methods
void unindex(int i) {
indexRemove(get(i));
}
void indexAdd(A a) {
Int i = index.get(a);
index.put(a, i == null ? 1 : i+1);
}
void indexRemove(A a) {
Int i = index.get(a);
if (i != null && i > 1)
index.put(a, i-1);
else
index.remove(a);
}
// static methods
static IndexedList2 ensureIndexed(L l) {
ret l instanceof IndexedList2 ? (IndexedList2) l : new IndexedList2(l);
}
}