180 likes | 293 Views
Computer Science 112. Fundamentals of Programming II List Iterators. Opening a List Iterator on a List. lyst = LinkedList( range (11, 21)) # or ArrayList(range(11, 21)) rator = aList.listIterator() rator.last() while rator.hasPrevious(): # print in reverse order
E N D
Computer Science 112 Fundamentals of Programming II List Iterators
Opening a List Iterator on a List lyst = LinkedList(range(11, 21)) # or ArrayList(range(11, 21)) rator = aList.listIterator() rator.last() while rator.hasPrevious(): # print in reverse order print(rator.previous()) rator lyst Maintains a cursor to access the list
Position-Based Operations for Navigation LI = L.listIterator() returns a new list iterator object on a list LI.first() moves the cursor to the first item LI.hasNext()returns true if there are any items following the current position LI.next()returns the next item and advances the position LI.last() moves the cursor to the last item LI.hasPrevious()returns true if there are any items preceding the current position LI.previous() returns the previous item and moves the position backward Similar to an extended iterator
Position-Based Operations for Mutation LI.insert(newItem) inserts newItem at the current position LI.remove() removes the last item returned by next or previous LI.replace(newItem) replaces the last item returned by next or previous
Mutations with a List Iterator lyst = LinkedList(range(11, 21)) # or ArrayList(range(11, 21)) # Replace all ints with 0s foriinrange(len(lyst)): lyst[i] = 0 Using an index-based loop with the subscript would be O(n2) with a linked list
Mutations with a List Iterator lyst = LinkedList(range(11, 21)) # or ArrayList(range(11, 21)) # Replace all ints with 0s rator = lyst.listIterator() whilerator.hasNext(): rator.next() rator.replace(0) Using an index-based loop with the subscript would be O(n2) with a linked list
Can Do Just One Insertion lyst = LinkedList(range(11, 21)) # or ArrayList(range(11, 21)) # Insert 1s before each integer rator = lyst.listIterator() whilerator.hasNext(): rator.next() rator.insert(1)
Can Do Just One Insertion lyst = LinkedList(range(11, 21)) # or ArrayList(range(11, 21)) # Error: must have a separate next() prior to each add rator = lyst.listIterator() whilerator.hasNext(): rator.next() rator.insert(1) rator.insert(2)
Using a Mutator to Clear the List lyst = LinkedList(range(11, 21)) # or ArrayList(range(11, 21)) # Clear the list (make it empty) rator = lyst.listIterator() whilerator.hasNext(): rator.next() rator.remove()
Can’t Use List Mutators lyst= LinkedList(range(11, 21)) # or ArrayList(range(11, 21)) # Clear the list (make it empty) rator = lyst.listIterator() whilerator.hasNext(): lyst.pop() rator.next() rator.remove() Directly mutating the backing store in the context of an iterator can cause the store and the iterator to become inconsistent The iterator will need to know when the store has changed and raise an exception in that event
Tracking Mutations • The list and its iterator each keep separate modCount variables • The list’s modCount is initially 0, and is incremented on each mutation • The iterator’s modCount is initialized to the list’s current modCount • Each call of next or previous compares the counts, and if they’re different, raises an exception
The List’s modCount classAbstractList(AbstractCollection): """Represents an abstract list.""" def__init__(self, sourceCollection): """Maintains a count of modifications to the list.""" self._modCount = 0 AbstractCollection.__init__(self, sourceCollection) defgetModCount(self): return self._modCount defincModCount(self): self._modCount += 1
The List’s modCount classArrayList(AbstractList): """Represents an array-based list.""" DEFAULT_CAPACITY = 8 def__init__(self, sourceCollection = None): self._items = Array(ArrayList.DEFAULT_CAPACITY) AbstractList.__init__(self, sourceCollection) defpop(self, i = len(self - 1)): """Precondition: 0 <= i < len(self) Removes and returns the item at position i.""" if i < 0 or i >= len(self): raiseIndexError("List index out of range") item = self._items[i] for j inrange(i, len(self) - 1): self._items[j] = self._items[j + 1] self._size -= 1 self.incModCount() # Track mutations! return item
The ListIterator Class classArrayList(AbstractList): """Represents an array-based list.""" deflistIterator(self): """Returns a list iterator.""" return ArrayList.ListIterator(self) Because the ListIterator will be implemented differently for each list implementation, we can nest it in the list class
The ListIterator Class classArrayList(AbstractList): """Represents an array-based list.""" deflistIterator(self): """Returns a list iterator.""" return ArrayList.ListIterator(self) classListIterator(object): """Represents the list iterator for an array list.""" def__init__(self, backingStore): self._backingStore = backingStore self._modCount = backingStore.getModCount() self.first() deffirst(self): """Returns the cursor to the beginning.""" self._cursor = 0 self._lastItemPos = -1 # Other ListIterator methods go here
The nextMethod classListIterator(object): """Represents the list iterator for an array list.""" defnext(self): """Preconditions: hasNext returns True The list has not been modified except by this iterator's mutators. Returns the current item and advances the cursor to the next item.""” ifnot self.hasNext(): raiseValueError("No next item in list iterator") if self._modCount != self._backingStore.getModCount(): raiseAttributeError("Illegal modification of backing store") self._lastItemPos = self._cursor self._cursor += 1 return self._backingStore[self._lastItemPos]
Moving from Right to Left def last(self): """Moves the cursor to the end of the backing store.""" self._cursor = len(self._backingStore) self._lastItemPos = -1 defhasPrevious(self): """Returns True if the iterator has a previous item or False otherwise.""" return self._cursor > 0 defprevious(self): """Preconditions: hasPrevious returns True The list has not been modified except by this iterator's mutators. Returns the current item and moves the cursor to the previous item.""" if not self.hasPrevious(): raiseValueError("No previous item in list iterator") self._lastItemPos = self._cursor - 1 self._cursor -= 1 return self._backingStore[self._lastItemPos]
For Wednesday Sorted Lists