Iterable
:
Object
Collection
|
:
AbstractCollection
List
|
|
Set
: |
|
:
AbstractList
AbstractSet
/
\
/
\
AbstractSequentialList
ArrayList HashSet TreeSet
/
LinkedList
Iterator interface—pg. 212-213 , parametrized by AnyType: where AnyType is the element type of the Collection.
boolean hasNext(); // the collection has a “next” object
AnyType next(); // get a ref to the next element object promised by hasNext, with the appropriate type
void remove(); // ignore for now
Idea—scan objects in a container by calling hasNext to see if there’s another, then if so, next to get it.
This is an interface, light as an idea. We need a real object to do anything for real. How to get one of these special objects???
Answer: ask a Collection for one!
That is, ask a concrete Collection class to get an Iterator object.
Look at Collection interface, pg. 211—
Note “Iterator<AnyType> iterator();”
That’s saying that to qualify as implementing the Iterable interface, required by the Collection interface, a class has to implement this method that returns an Iterator object.
Iterable<AnyType> promises that the class will generate iterators for us to use, via method " Iterator<AnyType>iterator();"
Now ArrayList, LinkedList, TreeSet and HashSet all implement Collection, so we already know that they provide Iterator objects. (Maps have their own interface separate from Collection--we'll cover this soon)
Example: iterate through an ArrayList al using Iterator:
ArrayList<String>
al = new
ArrayList<String>();
al.add(“ho”);
al.add(“hum”);
Iterator<String> itr =
al.iterator();
while (itr.hasNext())
System.out.print(itr.next());
prints “hohum”
Of course we could do this by a for loop
for
(s: al)
System.out.print(s);
Or even shorter, depending on ArrayList.toString():
System.out.print(al);
This would give us extra marks, [] around the list, etc.
So we have a choice of ways of scanning an ArrayList.
Ex: compute the total height of boxes in a Bin, using an Iterator (recall that boxes is an ArrayList of Box objects.)
Iterator<Box>
itr =
boxes.iterator();
int total = 0;
while (itr.hasNext()) {
Box b = itr.next();
total +=
b.height();
}
Skip 6.4 for now, return to it
Lists, collections with 0,
1, 2, 3, order of elements
Described by a List
interface, pg. 220
List = Collection + get/set methods + listIterator method
(actually more, but this is
Weiss’s important subset)
concrete JDK classes ArrayList,
LinkedList both implement List
get/set: express the 0, 1, 2, 3 ordering of lists
ArrayList—just like the 0, 1, 2, 3 ordering of arrays, O(1) speed for get/set
LinkedList—different implementation, can do get/set, but has to scan down from the beginning or end, so O(N) for get/set, where N=# elements.
Comparison of Implementation
ArrayList: implemented by an array of references, so imagine a sequence of little boxes, each with a reference to an object in it. The array is itself referenced from the basic object representing the whole ArrayList. When you add another object that would overfill the current array, another array, twice as big, is set up and all the objects are moved (just ref copies.)
LinkedList: implemented by a bunch (N in number) of little connector objects, themselves linked together like a necklace. Each connector object has three refs, one to its next connector, one to its previous connector, and one to the object that lives at this element position. In addition, there is an object for the whole list, and this links to the first and last connectors.
So we end up with the same idea of element positions 0, 1, 2, etc., but they are harder to reach by number.
Why is LinkedList a popular implementation?
Because you can add a new element at the beginning very easily, compared to ArrayList, and even add one in the middle.
See pg. 224 for some special LinkedList methods. Another method is add(index, Object) to add in the middle.
Iterator positions, and LinkedList Iterators
Element positions are quite clear: 0, 1, 2, …
Iterator positions are actually between element positions, and position x is just prior to element x.
An ordinary iterator starts at itr position 0, and hasNext looks at element position 0 to see if there’s a next object.
Next moves the iterator over element 0, returning it, and getting the iterator to itr position 1, just before element 1.
And so on, down to the last element at N – 1.
When the last element is returned, the iterator steps to position at the end of the list, position N.
Thus there are N +1 iterator positions for N elements: 0, 1, 2, …, N-1, N
A ListIterator is bi-directional, taking advantage of the previous pointers in the LinkedList it can be obtained from.
Example: collection of boxes as a LinkedList
LinkedList<Box> boxes = new LinkedList<Box>();
Box
b1
=
new Box(3);
Box
b2
=
new Box(8);
boxes.add(b1);
boxes.add(b2);
Note: can’t “set” these in, only can replace what’s in a spot with set().
Now, since a LinkedList implements Collection, we know we can use an ordinary iterator:
Same code as with ArrayList--
Iterator<Box> itr = boxes.iterator();
int total = 0;
while (itr.hasNext()) {
Box b = itr.next();
total +=
b.height();
}
But with a LinkedList, we can also use a ListIterator and go both ways along the list:
ListIterator<Box>
itr =
boxes.listIterator(0);
int total = 0;
while (itr.hasNext()) {
Box b = itr.next();
total +=
b.height();
}
if (itr.hasPrevious())
System.out.println(“last box is “ + itr.previous());
Stacks and Queues are specialized Lists--pa3 will use Stack extensively.
Sets
The Set interface is the same as the Collection interface according to pg. 229, and this is also true in the real JDK. However, you should be aware that Weiss’s Collection interface on pg. 211 is a simplification of the JDK Collection interface, and the missing methods are particularly useful for sets, allowing set intersection and union for example. We’ll cover this more advanced kind of set operation in cs310. For cs210, we’ll adopt Weiss’s simplified Collection interface and Set interface.
There’s more to a Set than the interface. The “fine print” of the contract says there may be no duplicate elements, and no order is preserved among the elements.
This follows what we do in math: A = { 1, 2, 3} = { 3, 2, 1}, and adding 2 to A gives us {1, 2, 3} because 2 is already there and no duplication is allowed.
The Collection interface provides a good model for a Set: for set A, we can say “is x in A?” by A.contains(x). We can add another element y to A by A.add(y). We can go through all the elements by using an iterator. And so on. Thus for cs210, the Set ADT will be defined by the Collection interface plus the requirement that there are no duplicate elements (and the understanding that there is no order preservation.) (In cs310, we’ll tackle Set union and intersection too.)
Set
Implementations
in the JDK
There are two major concrete classes implementing Set in the JDK, TreeSet and HashSet. You can read about them, pp. 210-216. We will not study their (actual) implementation in cs210, but will in cs310. In cs210, we will study binary search trees, which can be used to implement TreeSet, although not as well as the more advanced trees. The HashSet implementation requires “hashing”, a topic of cs310.
However, we can understand how to use these powerful JDK classes. It’s not difficult. For TreeSet, you need to have a way to compare elements, either through them implementing Comparable, or supplying a Comparator for them. For HashSet, you need element “equals” implemented, and also element hashCode.
The easiest cases are Set of String, or Set of Integer, or Set of Double, or …: these come with comparison and equals and hashCode already set up, so there’s hardly any work at all to using them. See the sample programs of Figures 6.26 and 6.27. Will be on hw2. Can simplifiy Fig. 6.26 by taking out "reverseOrder" spec.
Which to use, TreeSet or HashSet? For large problems, hashing is faster than tree search, O(1) vs O(log n), for n elements in the set. TreeSet maintains order, which can be a useful thing for the app.
You can say TreeSet implements SortedSet—see Figure 6.25. SortedSet is a JDK interface. But you don’t need to get “SortedSet” into the code: you can just use Set if those methods are enough for your app, and be assured that the iterator will return elements in sorted order.
Toy
example: vowels, think of as set--next time