AbstractList.java: Throw messages with IndexOutOfBoundsExceptions.

2000-11-02  Bryce McKinlay  <bryce@albatross.co.nz>

	* java/util/AbstractList.java: Throw messages with
	IndexOutOfBoundsExceptions.
	 (listIterator()): Call listIterator(0).
	(size): New field. Initialize to size().
	(hasNext): Test position against size, not size().
	(remove): Increment knownMod by one instead of resetting it from
	modCount.
	(add): Ditto.
	(SubList.upMod): Removed.
	(SubList.set): Don't call upMod() or update knownMod.
	(SubList.add(int,Object)): Increment modCount instead of calling
	upMod().
	(SubList.remove): Ditto.
	(SubList.addAll): Don't call backingList.size(). Increment size from
	c.size().
	(SubList.iterator): New method. Call listIterator(0).
	(SubList.listIterator): New method. Restore code to return an
	anonymous listIterator implementation (with some changes).
	* java/util/AbstractSequentialList.java: Throw messages with
	IndexOutOfBoundsExceptions.
	(addAll): Add a specnote.
	* java/util/ArrayList.java (removeRange): Get the math right.
	(addAll): Increment modCount _before_ creating iterator.
	* java/util/LinkedList.java: Rewritten, mostly.

From-SVN: r37203
This commit is contained in:
Bryce McKinlay 2000-11-02 10:08:03 +00:00 committed by Bryce McKinlay
parent 17e2e7f92d
commit 7177dab5c9
5 changed files with 660 additions and 455 deletions

View file

@ -1,3 +1,29 @@
2000-11-02 Bryce McKinlay <bryce@albatross.co.nz>
* java/util/AbstractList.java: Throw messages with
IndexOutOfBoundsExceptions.
(listIterator()): Call listIterator(0).
(size): New field. Initialize to size().
(hasNext): Test position against size, not size().
(remove): Increment knownMod by one instead of resetting it from
modCount.
(add): Ditto.
(SubList.upMod): Removed.
(SubList.set): Don't call upMod() or update knownMod.
(SubList.add(int,Object)): Increment modCount instead of caling upMod().
(SubList.remove): Ditto.
(SubList.addAll): Don't call backingList.size(). Increment size from
c.size().
(SubList.iterator): New method. Call listIterator(0).
(SubList.listIterator): New method. Restore code to return an anonymous
listIterator implementation (with some changes).
* java/util/AbstractSequentialList.java: Throw messages with
IndexOutOfBoundsExceptions.
(addAll): Add a specnote.
* java/util/ArrayList.java (removeRange): Get the math right.
(addAll): Increment modCount _before_ creating iterator.
* java/util/LinkedList.java: Rewritten, mostly.
2000-11-01 Tom Tromey <tromey@cygnus.com> 2000-11-01 Tom Tromey <tromey@cygnus.com>
* scripts/encodings.pl: Added `ASCII' alias. * scripts/encodings.pl: Added `ASCII' alias.

View file

@ -145,15 +145,22 @@ public abstract class AbstractList extends AbstractCollection implements List
return -1; return -1;
} }
/**
* Return an Iterator over this List. This implementation calls
* listIterator(0).
*
* @return an Iterator over this List
*/
public ListIterator listIterator() public ListIterator listIterator()
{ {
return new AbstractListItr(0); return listIterator(0);
} }
public ListIterator listIterator(int index) public ListIterator listIterator(int index)
{ {
if (index < 0 || index > size()) if (index < 0 || index > size())
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
size());
return new AbstractListItr(index); return new AbstractListItr(index);
} }
@ -193,10 +200,10 @@ public abstract class AbstractList extends AbstractCollection implements List
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public List subList(final int fromIndex, final int toIndex) public List subList(int fromIndex, int toIndex)
{ {
if (fromIndex > toIndex) if (fromIndex > toIndex)
throw new IllegalArgumentException(); throw new IllegalArgumentException(fromIndex + " > " + toIndex);
if (fromIndex < 0 || toIndex > size()) if (fromIndex < 0 || toIndex > size())
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
@ -208,6 +215,7 @@ public abstract class AbstractList extends AbstractCollection implements List
private int knownMod = modCount; private int knownMod = modCount;
private int position; private int position;
private int lastReturned = -1; private int lastReturned = -1;
private int size = size();
AbstractListItr(int start_pos) AbstractListItr(int start_pos)
{ {
@ -223,7 +231,7 @@ public abstract class AbstractList extends AbstractCollection implements List
public boolean hasNext() public boolean hasNext()
{ {
checkMod(); checkMod();
return position < size(); return position < size;
} }
public boolean hasPrevious() public boolean hasPrevious()
@ -235,7 +243,7 @@ public abstract class AbstractList extends AbstractCollection implements List
public Object next() public Object next()
{ {
checkMod(); checkMod();
if (position < size()) if (position < size)
{ {
lastReturned = position++; lastReturned = position++;
return get(lastReturned); return get(lastReturned);
@ -280,7 +288,7 @@ public abstract class AbstractList extends AbstractCollection implements List
throw new IllegalStateException(); throw new IllegalStateException();
} }
AbstractList.this.remove(lastReturned); AbstractList.this.remove(lastReturned);
knownMod = modCount; knownMod++;
position = lastReturned; position = lastReturned;
lastReturned = -1; lastReturned = -1;
} }
@ -298,7 +306,7 @@ public abstract class AbstractList extends AbstractCollection implements List
checkMod(); checkMod();
AbstractList.this.add(position++, o); AbstractList.this.add(position++, o);
lastReturned = -1; lastReturned = -1;
knownMod = modCount; knownMod++;
} }
} // AbstractList.Iterator } // AbstractList.Iterator
@ -311,7 +319,9 @@ public abstract class AbstractList extends AbstractCollection implements List
public SubList(AbstractList backing, int fromIndex, int toIndex) public SubList(AbstractList backing, int fromIndex, int toIndex)
{ {
backingList = backing; backingList = backing;
upMod(); // FIXME: The `this' prefixes in this class are a workaround for a
// gcj bug. They should be removed later.
this.modCount = backingList.modCount;
offset = fromIndex; offset = fromIndex;
size = toIndex - fromIndex; size = toIndex - fromIndex;
} }
@ -331,17 +341,6 @@ public abstract class AbstractList extends AbstractCollection implements List
throw new ConcurrentModificationException(); throw new ConcurrentModificationException();
} }
/**
* This method is called after every method that causes a structural
* modification to the backing list. It updates the local modCount field
* to match that of the backing list.
* Note that since this method is private, it will be inlined.
*/
private void upMod()
{
this.modCount = backingList.modCount;
}
/** /**
* This method checks that a value is between 0 and size (inclusive). If * This method checks that a value is between 0 and size (inclusive). If
* it is not, an exception is thrown. * it is not, an exception is thrown.
@ -352,7 +351,8 @@ public abstract class AbstractList extends AbstractCollection implements List
private void checkBoundsInclusive(int index) private void checkBoundsInclusive(int index)
{ {
if (index < 0 || index > size) if (index < 0 || index > size)
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
size);
} }
/** /**
@ -365,7 +365,8 @@ public abstract class AbstractList extends AbstractCollection implements List
private void checkBoundsExclusive(int index) private void checkBoundsExclusive(int index)
{ {
if (index < 0 || index >= size) if (index < 0 || index >= size)
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
size);
} }
public int size() public int size()
@ -379,7 +380,6 @@ public abstract class AbstractList extends AbstractCollection implements List
checkMod(); checkMod();
checkBoundsExclusive(index); checkBoundsExclusive(index);
o = backingList.set(index + offset, o); o = backingList.set(index + offset, o);
upMod();
return o; return o;
} }
@ -395,7 +395,7 @@ public abstract class AbstractList extends AbstractCollection implements List
checkMod(); checkMod();
checkBoundsInclusive(index); checkBoundsInclusive(index);
backingList.add(index + offset, o); backingList.add(index + offset, o);
upMod(); this.modCount++;
size++; size++;
} }
@ -404,7 +404,7 @@ public abstract class AbstractList extends AbstractCollection implements List
checkMod(); checkMod();
checkBoundsExclusive(index); checkBoundsExclusive(index);
Object o = backingList.remove(index + offset); Object o = backingList.remove(index + offset);
upMod(); this.modCount++;
size--; size--;
return o; return o;
} }
@ -417,19 +417,122 @@ public abstract class AbstractList extends AbstractCollection implements List
// this call will catch the toIndex < fromIndex condition // this call will catch the toIndex < fromIndex condition
backingList.removeRange(offset + fromIndex, offset + toIndex); backingList.removeRange(offset + fromIndex, offset + toIndex);
upMod(); this.modCount = backingList.modCount;
size -= toIndex - fromIndex; size -= toIndex - fromIndex;
} }
public boolean addAll(int index, Collection c) public boolean addAll(int index, Collection c)
{ {
checkMod(); checkMod();
checkBoundsInclusive(index); checkBoundsInclusive(index);
int s = backingList.size(); int csize = c.size();
boolean result = backingList.addAll(offset + index, c); boolean result = backingList.addAll(offset + index, c);
upMod(); this.modCount = backingList.modCount;
size += backingList.size() - s; size += csize;
return result; return result;
} }
} // AbstractList.SubList
public Iterator iterator()
{
return listIterator(0);
}
public ListIterator listIterator(final int index)
{
checkMod();
checkBoundsInclusive(index);
return new ListIterator()
{
ListIterator i = backingList.listIterator(index + offset);
int position = index;
public boolean hasNext()
{
checkMod();
return position < size;
}
public boolean hasPrevious()
{
checkMod();
return position > 0;
}
public Object next()
{
if (position < size)
{
Object o = i.next();
position++;
return o;
}
else
throw new NoSuchElementException();
}
public Object previous()
{
if (position > 0)
{
Object o = i.previous();
position--;
return o;
}
else
throw new NoSuchElementException();
}
public int nextIndex()
{
return offset + i.nextIndex();
}
public int previousIndex()
{
return offset + i.previousIndex();
}
public void remove()
{
i.remove();
SubList.this.modCount++;
size--;
position = nextIndex();
}
public void set(Object o)
{
i.set(o);
}
public void add(Object o)
{
i.add(o);
SubList.this.modCount++;
size++;
position++;
}
// Here is the reason why the various modCount fields are mostly
// ignored in this wrapper listIterator.
// IF the backing listIterator is failfast, then the following holds:
// Using any other method on this list will call a corresponding
// method on the backing list *after* the backing listIterator
// is created, which will in turn cause a ConcurrentModException
// when this listIterator comes to use the backing one. So it is
// implicitly failfast.
// If the backing listIterator is NOT failfast, then the whole of
// this list isn't failfast, because the modCount field of the
// backing list is not valid. It would still be *possible* to
// make the iterator failfast wrt modifications of the sublist
// only, but somewhat pointless when the list can be changed under
// us.
// Either way, no explicit handling of modCount is needed.
// However modCount++ must be executed in add and remove, and size
// must also be updated in these two methods, since they do not go
// through the corresponding methods of the subList.
};
}
} // AbstractList.SubList
} }

View file

@ -64,6 +64,12 @@ public abstract class AbstractSequentialList extends AbstractList
i.add(o); i.add(o);
} }
/**
* @specnote The spec in the JDK1.3 online docs is wrong. The implementation
* should not call next() to skip over new elements as they are
* added, because iterator.add() should add new elements BEFORE
* the cursor.
*/
public boolean addAll(int index, Collection c) public boolean addAll(int index, Collection c)
{ {
boolean modified = false; boolean modified = false;
@ -81,7 +87,8 @@ public abstract class AbstractSequentialList extends AbstractList
{ {
ListIterator i = listIterator(index); ListIterator i = listIterator(index);
if (index < 0 || index > size()) if (index < 0 || index > size())
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
size());
return i.next(); return i.next();
} }
@ -100,7 +107,8 @@ public abstract class AbstractSequentialList extends AbstractList
{ {
ListIterator i = listIterator(index); ListIterator i = listIterator(index);
if (index < 0 || index > size()) if (index < 0 || index > size())
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
size());
Object removed = i.next(); Object removed = i.next();
i.remove(); i.remove();
return removed; return removed;
@ -110,7 +118,8 @@ public abstract class AbstractSequentialList extends AbstractList
{ {
ListIterator i = listIterator(index); ListIterator i = listIterator(index);
if (index < 0 || index > size()) if (index < 0 || index > size())
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
size());
Object old = i.next(); Object old = i.next();
i.set(o); i.set(o);
return old; return old;

View file

@ -43,7 +43,7 @@ import java.io.ObjectStreamField;
* to or removing from the end of a list, checking the size, &c. * to or removing from the end of a list, checking the size, &c.
* *
* @author Jon A. Zeppieri * @author Jon A. Zeppieri
* @version $Id: ArrayList.java,v 1.6 2000/10/26 10:19:00 bryce Exp $ * @version $Id: ArrayList.java,v 1.2 2000/10/29 05:06:10 bryce Exp $
* @see java.util.AbstractList * @see java.util.AbstractList
* @see java.util.List * @see java.util.List
*/ */
@ -187,7 +187,7 @@ public class ArrayList extends AbstractList
if (fromIndex != toIndex) if (fromIndex != toIndex)
{ {
System.arraycopy(data, toIndex, data, fromIndex, size - toIndex); System.arraycopy(data, toIndex, data, fromIndex, size - toIndex);
size -= (fromIndex - toIndex); size -= (toIndex - fromIndex);
} }
} }
@ -219,9 +219,9 @@ public class ArrayList extends AbstractList
*/ */
public boolean addAll(Collection c) public boolean addAll(Collection c)
{ {
modCount++;
Iterator itr = c.iterator(); Iterator itr = c.iterator();
int csize = c.size(); int csize = c.size();
modCount++;
ensureCapacity(size + csize); ensureCapacity(size + csize);
for (int pos = 0; pos < csize; pos++) for (int pos = 0; pos < csize; pos++)
{ {
@ -240,13 +240,13 @@ public class ArrayList extends AbstractList
*/ */
public boolean addAll(int index, Collection c) public boolean addAll(int index, Collection c)
{ {
Iterator itr = c.iterator();
int csize = c.size();
modCount++;
if (index < 0 || index > size) if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
size); size);
modCount++;
Iterator itr = c.iterator();
int csize = c.size();
ensureCapacity(size + csize); ensureCapacity(size + csize);
int end = index + csize; int end = index + csize;
if (size > 0 && index != size) if (size > 0 && index != size)

File diff suppressed because it is too large Load diff