made the sub list cleaner and safer

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@994 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 7a341455b2
commit 59c6451fa8
  1. 51
      jode/jode/util/AbstractList.java

@ -325,26 +325,31 @@ public abstract class AbstractList extends AbstractCollection implements List {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public List subList(final int fromIndex, final int toIndex) { private static class SubList extends AbstractList {
// Note that within this class two fields called modCount are inherited - // Note that within this class two fields called modCount are inherited -
// one from the superclass, and one from the outer class. These are // one from the superclass, and one from the backing class. These are
// explicitly disambiguated in the code by referring to "this.modCount" // explicitly disambiguated in the code by referring to "this.modCount"
// and "AbstractList.this.modCount". // and "backing.modCount".
// The code uses both these two fields and *no other* to provide fail-fast // The code uses both these two fields and *no other* to provide fail-fast
// behaviour. For correct operation, the two fields should contain equal // behaviour. For correct operation, the two fields should contain equal
// values. Therefore, if this.modCount != AbstractList.this.modCount, there // values. Therefore, if this.modCount != backing.modCount, there
// has been a concurrent modification. This is all achieved purely by using // has been a concurrent modification. This is all achieved purely by using
// the modCount field, precisely according to the docs of AbstractList. // the modCount field, precisely according to the docs of AbstractList.
// See the methods upMod and checkMod. // See the methods upMod and checkMod.
return new AbstractList() { // Jikes doesn't want to access outer instance with AbstractList.this,
// since this is an AbstractList, too. I therefor changed class to static
// and do it by hand. This makes it a lot clearer by the way.
private AbstractList backing;
private final int offset;
private int size;
private final int offset = fromIndex; SubList(AbstractList backing, int fromIndex, int toIndex) {
private int size = toIndex - fromIndex; this.backing = backing;
this.offset = fromIndex;
this.size = toIndex - fromIndex;
{ // This is an instance initializer, called whenever this anonymous
// class is instantiated.
upMod(); upMod();
} }
@ -358,7 +363,7 @@ public abstract class AbstractList extends AbstractCollection implements List {
* concurrent modification. * concurrent modification.
*/ */
private void checkMod() { private void checkMod() {
if (this.modCount != AbstractList.this.modCount) { if (modCount != backing.modCount) {
throw new ConcurrentModificationException(); throw new ConcurrentModificationException();
} }
} }
@ -370,7 +375,7 @@ public abstract class AbstractList extends AbstractCollection implements List {
* Note that since this method is private, it will be inlined. * Note that since this method is private, it will be inlined.
*/ */
private void upMod() { private void upMod() {
this.modCount = AbstractList.this.modCount; modCount = backing.modCount;
} }
/** /**
@ -414,7 +419,7 @@ public abstract class AbstractList extends AbstractCollection implements List {
checkBoundsInclusive(index); checkBoundsInclusive(index);
return new ListIterator() { return new ListIterator() {
ListIterator i = AbstractList.this.listIterator(index + offset); ListIterator i = backing.listIterator(index + offset);
int position = index; int position = index;
public boolean hasNext() { public boolean hasNext() {
@ -498,7 +503,7 @@ public abstract class AbstractList extends AbstractCollection implements List {
public Object set(int index, Object o) { public Object set(int index, Object o) {
checkMod(); checkMod();
checkBoundsExclusive(index); checkBoundsExclusive(index);
o = AbstractList.this.set(index + offset, o); o = backing.set(index + offset, o);
upMod(); upMod();
return o; return o;
} }
@ -506,13 +511,13 @@ public abstract class AbstractList extends AbstractCollection implements List {
public Object get(int index) { public Object get(int index) {
checkMod(); checkMod();
checkBoundsExclusive(index); checkBoundsExclusive(index);
return AbstractList.this.get(index + offset); return backing.get(index + offset);
} }
public void add(int index, Object o) { public void add(int index, Object o) {
checkMod(); checkMod();
checkBoundsInclusive(index); checkBoundsInclusive(index);
AbstractList.this.add(index + offset, o); backing.add(index + offset, o);
upMod(); upMod();
size++; size++;
} }
@ -520,7 +525,7 @@ public abstract class AbstractList extends AbstractCollection implements List {
public Object remove(int index) { public Object remove(int index) {
checkMod(); checkMod();
checkBoundsExclusive(index); checkBoundsExclusive(index);
Object o = AbstractList.this.remove(index + offset); Object o = backing.remove(index + offset);
upMod(); upMod();
size--; size--;
return o; return o;
@ -532,7 +537,7 @@ public abstract class AbstractList extends AbstractCollection implements List {
checkBoundsInclusive(toIndex2); checkBoundsInclusive(toIndex2);
// this call will catch the toIndex2 < fromIndex2 condition // this call will catch the toIndex2 < fromIndex2 condition
AbstractList.this.removeRange(offset + fromIndex2, offset + toIndex2); backing.removeRange(offset + fromIndex2, offset + toIndex2);
upMod(); upMod();
size -= toIndex2 - fromIndex2; size -= toIndex2 - fromIndex2;
} }
@ -540,12 +545,16 @@ public abstract class AbstractList extends AbstractCollection implements List {
public boolean addAll(int index, Collection c) { public boolean addAll(int index, Collection c) {
checkMod(); checkMod();
checkBoundsInclusive(index); checkBoundsInclusive(index);
int s = AbstractList.this.size(); int s = backing.size();
boolean result = AbstractList.this.addAll(offset + index, c); boolean result = backing.addAll(offset + index, c);
upMod(); upMod();
size += AbstractList.this.size() - s; size += backing.size() - s;
return result; return result;
} }
};
} }
public List subList(final int fromIndex, final int toIndex) {
return new SubList(this, fromIndex, toIndex);
}
} }

Loading…
Cancel
Save