Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chapter 23 Organizing list implementations. This chapter discusses n The notion of an iterator. n The standard Java library interface Collection, and.

Similar presentations


Presentation on theme: "Chapter 23 Organizing list implementations. This chapter discusses n The notion of an iterator. n The standard Java library interface Collection, and."— Presentation transcript:

1 Chapter 23 Organizing list implementations

2 This chapter discusses n The notion of an iterator. n The standard Java library interface Collection, and some of its related classes.

3 A library structure n We have yet to discuss how all the lists that we have implemented are related. n We could organize them like this:

4 n With this approach we encounter problems when we try to extend the base class for other purposes, such as adding new functionality. n This approach causes class explosion as each circumstance must be implemented in each subclass. A library structure (cont.)

5 n The problem is that the class List is a participant in two distinct hierarchies: an implementation hierarchy and a concrete application hierarchy. n Solution: Use composition rather than extension to handle different implementation strategies.

6 A library structure (cont.) n Build a separate implementation hierarchy. n Provide each list with an implementation as a component. n This kind of structure is called a bridge.

7 Implementing List with a bridge public abstract class List implements Cloneable { … public Object get (int i) { return imp.get(i); } … } public interface ListImplementation extends Cloneable { … Object get (int i); … }

8 Implementing List with a bridge (cont.) n The ListImplementation subclasses are now concrete classes. Each concrete ListImplementation subclass must provide an appropriate definition of the method get. class BoundedList implements ListImplementation { … public Object get (int i) { return elements[i]; } … }

9 Specifying the implementation n A ListImplementation is created when a List is created. n We make the client responsible for determining which implementation to use when creating the List. n This means that deciding which implementation to use for a particular List is not done until run-time.

10

11

12

13 Iterators Many of the methods used with List are linear. e.g. indexOf, remove. n The problems of examining each element of a container and of obtaining a handle on a particular container element are very general. n An iterator is an object associated with a particular container that provides a means of sequentially accessing each element in the container.

14 Iterators (cont.) public interface Iterator extends Cloneable Iterator for accessing and traversing elements of a container. public void reset () Initialize this Iterator to reference the first item. public void advance () Advance this Iterator to the next item. require: !this.done()

15 Iterators (cont.) public boolean done () No more items to traverse in the container. public Object get () Container item this Iterator currently references. require: !this.done() public boolean equals (Object obj) The specified Object is an Iterator of the same class as this, and references the same relative item of the same container.

16 Iterators (cont.) Assuming c is a container of some sort and i an iterator associated with it, we can access each item in the container as follows: i.reset(); while (!i.done()) { do something with i.get(i); i.advance(); }

17 Iterators (cont.) An int variable used to index a list is a simple form of iterator. n It is reset by assigning a value of 0, and advanced by incrementing. n The iterator is done when it equals the length of the list. n For two Iterators to be equal, they must reference the same relative item of the same container. n Even if index 3 and 5 are referencing the same object, an Iterator that references the item with index 3 would not be equal to an Iterator that references the item with index 5.

18 Iterator classes n If an interface is to traverse a container efficiently, it must be linked closely to the container implementation. n Therefore we create classes for each type of container.

19 ListIterator n ListIterator implements an Iterator for arrays. n When a ListIterator is created, it is given a reference to the ListImplementation it will traverse. n The current element referenced by the Iterator is represented simply as an integer index.

20

21

22 LinkedListIterator n In a LinkedList, it is preferable to keep a reference to a Node, which can be advanced efficiently to reference the next Node in the list. n Iterator must have access to the implementation structure of the LinkedList. n A LinkedListIterator keeps a reference to the Node containing the current item.

23

24

25 Creating an Iterator n Since an Iterator is intimately bound to the List it is traversing, we add functionality for creating an Iterator to the class List. n List forwards the responsibility to its ListImplementation. public abstract class List implements Cloneable { … /** * Create a new Iterator for this List. */ public Iterator iterator () { return new imp.iterator(); } … }

26 Creating an Iterator (cont.) n ListImplementation defines a factory method that produces the appropriate kind of Iterator. interface ListImplementation extends Cloneable { … /** * Create a new Iterator for this List. */ public Iterator iterator (); … }

27 Creating an Iterator (cont.) n Concrete implementation classes implement the factory method to produce an appropriate iterator. class LinkedList extends ListImplementation { … /** * Create a new Iterator for this List. */ public Iterator iterator (){ return new LinkedListIterator(this); } … }

28 Creating an Iterator (cont.)

29

30

31 List methods with iterators as arguments n We overload the List methods that take index arguments with methods taking iterators as arguments.

32 List methods with iterators as arguments (cont.) public Object get (Iterator i) The element referenced by the specified Iterator. require: this.traversedBy(i) !i.done() public Iterator iteratorAt (Object obj) An Iterator referencing the first occurrence of the specified element in this List; Iterator is done if this List does not contain the specified element. require: obj != null ensure: if obj equals no element of this List then iteratorAt(obj).done() else obj.equals(iteratorAt(obj).get()), and iteratorAt(obj) references the first position in a tarversal for which this is true.

33 List methods with iterators as arguments (cont.) public void add (Iterator i, Object obj) Insert the specified Object at the specified position. require: this.traversedBy(i) !i.done() obj != null ensure: this.size() == old.size() + 1 i.get() == obj (i.advance(); i.get()) == old.i.get() public void remove (Iterator i) Remove the element at the specified position. require: this.traversedBy(i) !i.done() ensure: this.size() == old.size() - 1 i.get() == (old.i.advance(); old.i.get())

34 List methods with iterators as arguments (cont.) public void set (Iterator i, Object obj) Replace the element at the specified position with the specified Object. require: this.traversedBy(i) !i.done() public boolean traversedBy (Iterator i) This List is traversed by the specified Iterator.

35 List methods with iterators as arguments (cont.) The final postconditions for add and remove indicate a sequene of method calls. The add postcondition (i.advance(); i.get()) == old.i.get() indicates that advancing the iterator followed by a get gives the same element get would have returned before the add. The remove postcondition i.get() == (old.i.advance(); old.i.get()) indicates that the element referenced by the iterator after the remove is the one following the element that was removed.

36 List methods with iterators as arguments (cont.) n The implementation of these methods is straightforward. public Object get (Iterator i) { Require.condition(this.traversedBy(i)); return i.get(); } n Most other operations are forwarded to the ListImplementation. public void remove (Iterator i) { Require.condition(this.traversedBy(i)); imp.remove(i); }

37 Improving LinkedListIterator n We defined LinkedListIterator that referenced the current node of a LinkedList.

38 Improving LinkedListIterator (cont.) This works fine for get and set, but when we try to implement remove and add, we notice that we need a reference to the Node preceding the current Node. n There are several solutions: keep a pair of references in the Iterator one to the current Node and one to the preceding Node. n We could also simply keep a reference to the Node preceding the current one. n Boundary cases are simplified if LinkedList has a header.

39 Iterato r extensions n We define Iterator extensions that capture the notion of a circular list, and that permit forward and backward traversal of a list. n We can ensure that an Iterator created by a DoublyLinkedList implements the interface CircularIterator. u Now the iterator can be moved backward of forward in a circular fashion.

40 Iterator extensions (cont.) public interface WrappingIterator extends Iterator An Iterator that returns to the beginning of the enumeration when advanced past the last element of the container. done is true if the Iterator s referencing the first item of the enumeration, having been advanced from the last item, or if the container is empty. public void advanced () Advance this Iterator to the next item. Advance to the first item if this Iterator is currently referencing the last item in the enumeration. require: The container this Iterator is referencing is not empty.

41 Iterator extensions (cont.) public boolean done () This Iterator currently references the first item of the enumeration having been advanced from the last, or the container is empty. public Object get () Container item this Iterator currently references. require: The container this Iterator is referencing is not empty.

42 Iterator extensions (cont.) public interface BiDirectionalIterator extends Iterator An Iterator that can move to previous as well as next item. offRight is true if the Iterator has been advanced past the last element, or if the container is empty. offLeft is true if the Iterator has been backed up past the first element, or if the container is empty. public boolean done () This Iterator has been advanced past the last element, or the container is empty. Equivalent to offRight.

43 Iterator extensions (cont.) public boolean offRight () This Iterator has been advanced past the last element, or the container is empty. Equivalent to done. public boolean offLeft () This Iterator has been backed up past the first element, or the container is empty. public void backup () Move this Iterator back to the previous element.

44 Iterator extensions (cont.) public interface CircularIterator extends WrappingIterator, BiDirectionalIterator An Iterator can move to next or previous item in the container, and wraps at the ends of the enumeration. That is, moves to the first element when advanced past the last element, and moves to the last element when backed up from the first element. If the container is not empty, the Iterator references the first element of the enumeration when offRight (done) is true. If the container is not empty, the Iterator references the last element of the enumeration when offLeft is true. public void advance () Advance this Iterator to the next item. Advance to the first item if this Iterator is currently referencing the last item in the enumeration. require: The container this Iterator is referencing is not empty.

45 Iterator extensions (cont.) public void backup () Move this Iterator back to the previous item. Move to the last item if this Iterator is currently referencing the first item in the enumeration. require: The container this Iterator is referencing is not empty.

46 Iterators and List modification n More than one Iterator can be traversing the same list. Suppose an Iterator i is referencing a particular element of a List list, for instance the element with index 2:

47 Iterators and List modification (cont.) n The specifications promise that if we delete the element referenced by the Iterator, the Iterator will reference the next element.

48 Iterators and List modification (cont.) The specifications promise that if we next do list.add(i, x);

49 Iterators and List modification (cont.) n How does an Iterator behave if the List is modified by means of another Iterator, or by means of an index? n If we do list.remove(j); or l.remove(2); what will the state of i be?

50 Iterators and List modification (cont.) n We could build Iterators that are Observers of an Observable List. u The Iterators register with the List. u The List informs all its Iterators whenever it is modified structurally. n Instead, we assume that if a List is modified by index, all Iterators that reference the List become invalid. n Because, Iterators typically have very local scope and short lifetimes, this does not present serious practical problems.

51 Iterators and List modification (cont.) n We could add methods to the class List that take several Iterators as arguments. public void remove (Iterator i1, Iterator i2) Delete all the elements of this List from the element specified by the first Iterator through the element specified by the second, inclusive. n The postconditions describe the state of the Iterators after the method is executed.

52 Internal or passive Iterators n Internal or passive Iterators shift the responsibility from the client to the iterator. n A client provides an operation and the iterator applies the operation to each element of the container. n When the Iterator is created, it is provided with a List, a condition, and an operation.

53 Internal or passive Iterators (cont.) public interface Predicate { public boolean evaluate (Object obj); } public interface Operation { public void execute (Object obj); }

54 Internal or passive Iterators (cont.) n The internal iterator constructor takes a List, Predicate, and Operation as arguments. n Its single command applies the Operation to all List elements that satisfy Predicate. public class ListTraverse Internal iterator that performs a spcified operation on each List element that satisfies a given condition. public ListTraverser (List list, Predicate p, Operation op) Create a new iterator with the specified List, Predicate, and Operation. public void traverse () Apply the Operation to each element of the List that satisfies the Predicate.

55 Internal or passive Iterators (cont.) An Iterator to print out all students on StudentList CourseList who have a final average greater than 90. ListTraverser listA = new ListTraverser ( new Predicate () { public boolean evaluate (Object obj) { return ((Student)obj).finalAve()>90; } }, new Operation () { public void execute (Object obj) { System.out.println( ((Student)obj).name()); } }, courseList);

56 Internal or passive Iterators (cont.) n The Iterator defines anonymous classes. To perform the iteration, we give the Iterator the traverse command: listA.traverse();

57 Comparing implementations

58 The java.util Collection hierarchy The standard Java package java.util defines the interface Collection. n The interface Collection models a rather generalized container. public boolean contains (Object o) This collection contains the specified element. public boolean isEmpty () This collection contains no elements. public int size () The number of elements in this collection. public java.util.Iterator iterator() An iterator over the elements in this collection.

59 The java.util Collection hierarchy (cont.) n Operations to add and remove elements are optional. n Example: public boolean add (Object o) throws UnsupportedOperationException, ClassCastException, IllegalArgument Exception {…}

60 The java.util Collection hierarchy (cont.) If the operation add is not supported by the implementing class, an UnsupportedOperationException is thrown. If the class of the argument prevents it from being added to the Collection, a ClassCastException is thrown. If any aspect of of the object other than its class prevents it from being added to the Collection, an IllegalArgument is thrown.

61 List n List is an interface that extends Collection. n It includes: public Object get (int index) The element at the specified position in this List.

62 Hierarchy n Corresponding to the interfaces Collection, List, and Set are abstract classes AbstractCollection, AbstractList, and AbstractSet. n Array-based list implementations such as java.util.Vector extend AbstractList directly. n Linked implementations, such as java.util.LinkedList, extend the abstract class AbstractSequentialList, which extends AbstractList.

63 Hierarchy (cont.)

64 Iterators The java.util interface Iterator specifies three methods: public boolean hasNext() The iteration has more elements.next public Object next () throws NoSuchElementException The next element in the interation. Throws NoSuchElementException if hasNext() is false. public void remove () throws UnsupportedOperationException, IllegalStateException Removes from the underlying collection the last element returned by the iterator (optional operation). This method can be called only once per call to next.

65 Iterator (cont.) next is not a proper query since it changes the state of the iterator. public Object next () { Object temp = this.get(); this.advance(); return temp; }

66 Weve covered n Organizing list classes into a coherent library structure. n Separating the List abstraction hierarchy from the implementation hierarchy by use of a bridge. n Method performance. n External Iterators. n Internal Iterator abstraction. Collection interfaces and abstraction found in the standard Java Package java.util.

67 Glossary


Download ppt "Chapter 23 Organizing list implementations. This chapter discusses n The notion of an iterator. n The standard Java library interface Collection, and."

Similar presentations


Ads by Google