![]() |
Algorithms and Data Structures | ||||
|
Generic
Lists
![]() The initial definition of the List class only allowed us to have lists of integers. What we would really like is to have a list of any type, class, object, what you will. We want to do ths while preserving the functionality of our integer list. That is, we want methods for delete, insert, etc for any class. The Polymorphic List Class, and its methods (java code for the generic List class) Our first definition of the List Class, and its methods is defined textually below. A List is defined as a triple: boolean eol; Object data; List next;This is very similar to the definition used before except that instead of data being an integer (int) it is now an Object. The constructors The constructors are the same as before, except that we have e as an Object.
The accessors Again, we have the 3 accessor functions, but now head delivers an Object.
To print a list (using the toString method) In java every object should have a toString() method. This is then used by System.out.println. That is, System.out.println(X) applies the toString method to the object X, delivering a string. The System.out.println method is then applied to that string. So, to print a List we should really just have a method that takes a List and delivers a string representation for printing. So, if we have a list L we can print it just like any other object by calling System.out.println(L). We will use the convention that the printed image of a list starts with a "(" and ends with a ")". The method toString below just delivers an open round bracket "(", calls a method to deliver the rest of the list as a string (RestOfString), and then delivers a closing round bracket ")". Note that the operator + is over loaded by java so that it works between strings, concatenating strings ("Pat"+"rick"). public String toString() { return "(" + RestOfString() + ")"; }To deliver the list as a string we use method RestOFString below. Note that it is private so cannot be accessed outside of the class definition, but it may be used by the methods within the class definition (and toString in particular). private String RestOfString() { if (isEmpty()) return ""; else return head().toString() + " " + tail().RestOfString(); }Method RestOfString is very similar to the print method, viewed as a pattern, but is a bit more interesting. It's similar because it deals with the situation of the list being empty (isEmpty) and delivers the null string "", and if the list is not empty, doing something with the head of the list (head()) and then making a recursive call with the tail of the list (tail().RestOfString()). What is interesting is the application of the toString method to the head of the list. Isn't that a recursive call to the method we are defining? And does that not suggest that the method will not terminate? In fact, since head() now delivers an Object, and we expect all objects to have a toString method, java should work out just what to do here. So, it generally is not a recursive call to the toString method defined here. But ... it might be! It would be if the head() is a List! So, we can print a list of lists, as well as a list of any objects (so long as they have a toString method)! The isEmpty, length, append, delete, and reverse methods These methods are unchanged. The add method The add method only has one minor change: it now takes as argument an Object e (rather than an int e). The insert method Previously, the insert method delivered as a result a new list with the integer e inserted into the List L, retaining the increasing order of the list. But how do we insert an arbitrary object into a list in order? What happens if that element is an animal (a dog, cat, or elephant) into a list of animals, or a task into a list of tasks, or books into a list of books? If we want our List class to be generic we must be able to do this. We do this by using interfaces. The idea is as follows. To insert an object into a list we want the user to define the concept of order between objects. So, we will have a class of object called a comparator (for wont of a name). The comparator class is essentialy empty, having no attributes, but has a method for comparing two objects. The insert method is then passed:
1. public List insert(Object e, Comparator c) 2. { 3. if (isEmpty()) 4. return new List(e); 5. else if (c.compare(e,head()) < 0) 6. return new List(e,this); 7. else return new List(head(),tail().insert(e,c)); 8. }I'll define the method, numbered line by numbered line, below:
Source Code Acknowledgements Ewan MacIntyre (aka Ewen MacIntypo) and Andrew Forrest helped me make the list generic, and then helped me apply it to ToDo and Integer. And they never shouted at me (at least, not to my face.) |