static class HybridTokens extends AbstractList { Tokenization tok; L pointers; static bool debug; static int instances; sclass LinkedToken { S t; int index = -1; LinkedToken prev, next; LinkedToken prevIdentical, nextIdentical; *() {} *(S *t) {} } sclass Tokenization { LinkedToken first, last; new Map firstByContent; new Map lastByContent; bool contains(S t) { ret firstByContent.get(t) != null; } int countInstances(S t) { int n = 0; LinkedToken lt = firstByContent.get(t); while (lt != null) { ++n; lt = lt.nextIdentical; } ret n; } } *() { ++instances; } *(L tokens) { this(); tok = makeTokenization(tokens); pointers.ensureCapacity(l(tokens)); } // required immutable list methods @Override public S get(int i) { int j = max(size(), } @Override public int size() { if (last(pointers) != tok.last) { LinkedToken lt = last(pointers); if (lt == null) lt = tok.first; if (lt != null) while ((lt = lt.next) != null) pointers.add(lt); } ret l(pointers); } // required mutable list methods @Override public S set(int i, S a) { LinkedToken lt = get(i); if (eq(lt.t, a)) ret; // Take out of old content chain if (lt.prevIdentical == null) tok.firstByContent.remove(a); else lt.prevIdentical.nextIdentical = lt.nextIdentical; if (lt.nextIdentical == null) tok.lastByContent.remove(a); else lt.nextIdentical.prevIdentical = lt.prevIdentical; // Add to new content chain lt.prevIdentical = lt_findPrevIdentical(lt); if (lt.prevIdentical == null) tok.firstByContent.put(a, lt); lt.nextIdentical = lt_findNextIdentical(lt); if (lt.nextIdentical == null) tok.lastByContent.put(a, lt); // Set new value and return old one S prev = lt.t; lt.t = a; ret prev; } @Override public void add(int i, S a) { LinkedToken lt = get(i); if (lt == null) { assertTrue(i == size()); lt_addToken(tok, a); } else { LinkedToken ltNew = new(a); ltNew.last = lt.last; if (lt.last != null) lt.last.next = ltNew; else tokens.first = ltNew; ltNew.next = lt; lt.last = ltNew; lt_addToContentChain(lt, tok); clearPointersFrom(i); } } @Override public S remove(int i) { S a = l.get(i); index.remove(a); l.remove(i); ret a; } // speed up methods @Override protected void removeRange(int fromIndex, int toIndex) { for (int i = fromIndex; i < toIndex; i++) unindex(i); l.subList(fromIndex, toIndex).clear(); } @Override public int indexOf(O a) { LinkedToken lt = tok.firstByContent(a); if (lt == null) ret -1; makeIndex(lt); ret lt.index; } @Override public bool contains(O a) { ret tok.contains((S) a); } @Override public void clear() { index.clear(); l.clear(); } @Override public bool addAll(int i, Collection c) { index.addAll((Collection) c); ret l.addAll(i, c); } // indexing methods void makeIndex(LinkedToken lt) { if (lt.index >= 0) ret; LinkedToken l = lt.prev; while (l != null && l.index < 0) l = l.prev; int index = 0; if (l == null) l = tok.first; while true { l.index = index++; if (l == lt) break; l = l.next; } } // static methods static HybridTokens ensureIndexed(L l) { ret l instanceof HybridTokens ? (HybridTokens) l : new HybridTokens(l); } }