Fix iterator implementation

This commit is contained in:
fullwall 2013-11-11 11:53:41 +08:00
parent 3ef703bdcd
commit a80f9c6cf4
2 changed files with 42 additions and 27 deletions

View File

@ -78,7 +78,7 @@ public class ByIdArray<T> implements Iterable<T> {
@Override @Override
public Iterator<T> iterator() { public Iterator<T> iterator() {
return new Itr(); return new Itr2();
} }
public void put(int index, T t) { public void put(int index, T t) {
@ -141,11 +141,12 @@ public class ByIdArray<T> implements Iterable<T> {
} }
} }
private class Itr implements Iterator<T> { private class Itr2 implements Iterator<T> {
private int expected = ByIdArray.this.modCount; int cursor;
private int idx; int expectedModCount = modCount;
int lastRet = -1;
private Itr() { public Itr2() {
if (size > 0) { if (size > 0) {
if (lowest > highest || highest == Integer.MIN_VALUE || highest >= elementData.length if (lowest > highest || highest == Integer.MIN_VALUE || highest >= elementData.length
|| elementData[highest] == null) { || elementData[highest] == null) {
@ -154,47 +155,54 @@ public class ByIdArray<T> implements Iterable<T> {
if (lowest > highest || lowest >= elementData.length || elementData[lowest] == null) { if (lowest > highest || lowest >= elementData.length || elementData[lowest] == null) {
recalcLowest(); recalcLowest();
} }
idx = lowest; cursor = lowest;
} }
} }
private void advance() { private void advance() {
do { do {
idx++; cursor++;
} while (idx != highest + 1 && elementData[idx] == null); } while (cursor != highest + 1 && elementData[cursor] == null);
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
} }
@Override @Override
public boolean hasNext() { public boolean hasNext() {
if (modCount != expected) { return size > 0 && highest >= cursor;
throw new ConcurrentModificationException();
}
return size > 0 && highest >= idx;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T next() { public T next() {
if (modCount != expected) checkForComodification();
int i = cursor;
if (cursor > highest)
throw new NoSuchElementException();
Object[] elementData = ByIdArray.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException(); throw new ConcurrentModificationException();
if (idx > highest)
throw new NoSuchElementException();
T next = (T) elementData[idx];
if (next == null)
throw new NoSuchElementException();
advance(); advance();
return next; return (T) elementData[lastRet = i];
} }
@Override @Override
public void remove() { public void remove() {
if (modCount != expected) if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ByIdArray.this.fastRemove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException(); throw new ConcurrentModificationException();
if (elementData[idx] == null) }
throw new NoSuchElementException();
fastRemove(idx);
expected = modCount;
advance();
} }
} }

View File

@ -58,9 +58,16 @@ public class ByIdArrayTest {
itr.remove(); itr.remove();
itr.next(); itr.next();
assertSize(array, 2); assertSize(array, 2);
assertThat(array.contains(20), is(false)); assertThat(array.contains(10), is(false));
assertThat(array.get(10), is(1)); assertThat(array.get(20), is(2));
assertThat(array.get(30), is(3)); assertThat(array.get(30), is(3));
itr = array.iterator();
while (itr.hasNext()) {
itr.next();
itr.remove();
}
assertSize(array, 0);
} }
@Test @Test