Tải bản đầy đủ (.pdf) (12 trang)

Custom Implementations

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (29.3 KB, 12 trang )

Chapter 14: Custom Implementations
Overview
All the earlier chapters of the book mention that every concrete implementation class in the Collections
Framework extends from an abstract implementation. In fact, there are five abstract classes that form the basis
of every system−defined collection introduced by the framework: AbstractCollection, AbstractSet,
AbstractList, AbstractSequentialList, and AbstractMap. Some historical collection classes like Hashtable,
however, do not extend from these classes though. Figure 14−1 shows the relationships between the abstract
classes through their class hierarchy. Like the concrete implementations, the map stands alone.
Figure 14−1: Class hierarchy of the abstract collection classes.
These abstract implementations make creating custom implementations very easy. All you have to do is
subclass and provide a handful of methods specific to your implementation.
AbstractCollection Class
The AbstractCollection class provides an abstract implementation of the Collection interface. It is essentially a
bag−type collection, not necessarily a set or a list. Table 14−1 lists the one constructor and the methods of the
class.
Table 14−1: Summary of the AbstractCollection Class
VARIABLE/METHOD
NAME
VERSION DESCRIPTION
AbstractCollection() 1.2 Constructs an empty (abstract) collection.
add() 1.2 Adds an element to the collection.
addAll() 1.2 Adds a collection of elements to the collection.
clear() 1.2 Clears all elements from the collection.
contains() 1.2 Checks if the collection contains an element.
containsAll() 1.2 Checks if the collection contains a collection of elements.
isEmpty() 1.2 Checks if the collection is empty.
iterator() 1.2 Returns an object from the collection that allows all of the
collection's elements to be visited.
remove() 1.2 Clears a specific element from the collection.
removeAll() 1.2 Clears a collection of elements from the collection.
178


retainAll() 1.2 Removes all elements from collection not in another collection.
size() 1.2 Returns the number of elements in a collection.
toArray() 1.2 Returns the elements of the collection as an array.
toString() 1.2 Converts the collection contents into a string.
Subclassing AbstractCollection
If you wish to create a concrete implementation based upon the AbstractCollection class, you must at a
minimum implement two constructors and define two methods.
The AbstractCollection class has only one constructor:
protected AbstractCollection()
In your custom implementation, you must provide a no−argument constructor and a copy constructor:
public MyCollection()
public MyCollection(Collection col)
As far as the two methods go, you must implement the abstract iterator() and size() methods:
public abstract iterator Iterator()
public abstract int size()
The iterator() method returns an Iterator over the collection. The size() method returns the number of elements
in the collection. With these two methods implemented, you have a usable collection, though it isn't
modifiable.
Implementing Optional Methods
The Collections Framework relies on optional interface methods to offer additional behavior. If the methods
aren't overridden, they provide a default behavior of throwing the UnsupportedOperationException. For your
collection to be a little more useful, you need to override the add() method in your collection and provide a
remove() method in your iterator:
public boolean add(Object element) // In AbstractCollection
public void remove() // In Iterator
Tip Don't override the remove() method of AbstractCollection unless you are doing it for performance
reasons. Remember that you must implement remove() in your collection's iterator.
You do not have to define both methods, although if you are supporting one operation, it usually makes sense
to support the other.
The remaining methods of AbstractCollection all rely on size() and iterator() for their behavior. You do not

have to override any, though for performance reasons you may choose to do so. The choice is yours.
Tip For performance reasons, you may wish to override isEmpty() so it doesn't rely on size() to
determine whether the collection is empty. This avoids the 0(n) cost of calling size().
Subclassing AbstractCollection
179
AbstractSet Class
The use of an AbstractSet is identical to an AbstractCollection, with the only exception being that, by
definition, the set cannot contain duplicates. The class only defines three methods and a constructor with the
rest of the behavior directly inherited from AbstractCollection. The methods and constructor of AbstractSet
are listed in Table 14−2.
Table 14−2: Summary of the AbstractSet Class
VARIABLE/METHOD NAME VERSION DESCRIPTION
AbstractSet() 1.2 Constructs an empty set.
equals() 1.2 Checks for equality with another
object.
hashCode() 1.2 Computes a hash code for the set.
removeAll() 1.2 Clears a collection of elements
from the set.
Defining an abstract set has the same requirements as defining an abstract collection: two constructors and
two methods, or four methods if you wish to support updates. If your custom set also implements SortedSet,
then you must provide two additional constructors:
public MySet(Comparator comp)
public MySet(SortedSet set)
The requirement to enforce uniqueness of elements is placed on your subclass of AbstractSet, not within the
abstract class itself.
Creating a Custom Set
Early versions of the Java 2 platform included an ArraySet. This class provided a Set implementation that,
compared to HashSet, was rather performance crippled to find an element beyond about five elements. It does,
however, provide a good basis for a custom set implementation. Behind the scenes, the class relies on an
ArrayList for the actual storage. When adding elements as well as with the copy constructor, be extra careful

not to add duplicates.
The set implementation in Listing 14−1 goes beyond the basics necessary to create a custom set. Instead of
just defining the minimum, it supports serialization as well as cloning and optimizes several of its operations.
It is meant to be a usable set implementation, not just a toy. Also, since ArraySet relies on an ArrayList for its
backing store, it isn't necessary to define our own iterator.
Listing 14−1: Custom ArraySet implementation.
import java.io.Serializable;
import java.util.*;
public class ArraySet extends AbstractSet
implements Cloneable, Serializable {
private ArrayList list;
public ArraySet() {
list = new ArrayList();
AbstractSet Class
180
}
public ArraySet(Collection col) {
list = new ArrayList();
// No need to check for dups if col is a set
Iterator itor = col.iterator();
if (col instanceof Set) {
while (itor.hasNext()) {
list.add(itor.next());
}
} else {
while(itor.hasNext()) {
add(itor.next());
}
}
}

public Iterator iterator() {
return list.iterator();
}
public int size() {
return list.size();
}
public boolean add(Object element) {
boolean modified;
if (modified = !list.contains(element)) {
list.add(element);
}
return modified;
}
public boolean remove(Object element) {
return list.remove(element);
}
public boolean isEmpty() {
return list.isEmpty();
}
public boolean contains(Object element) {
return list.contains(element);
}
public void clear() {
list.clear();
}
public Object clone() {
try {
ArraySet newSet = (ArraySet)super.clone();
newSet.list = (ArrayList)list.clone();
return newSet;

} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}
}
AbstractSet Class
181
Note Remember that sets are supposed to be unordered, so even though the collection is backed by an array,
there is no sequential access outside the iterator. The iterator will return the elements in the order they
were added, however, as defined by ArrayList.
Pulling in an example from Chapter 8, all you have to do is change the constructor call to test our new
ArraySet class as shown in Listing 14−2:
Listing 14−2: Testing our new ArraySet implementation.
import java.util.*;
public class SetTest {
public static void main (String args[]) {
String elements[] = {"Irish Setter", "Poodle",
"English Setter", "Gordon Setter", "Pug"};
Set set = new ArraySet(Arrays.asList(elements));
Iterator iter = set.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
}
AbstractList Class
The AbstractList class forms the basis for creating lists that support random access, partially implementing the
List interface and adding some new methods of its own. Table 14−3 lists the methods of the AbstractList
class.
Table 14−3: Summary of the AbstractList Class

VARIABLE/METHOD
NAME
VERSION DESCRIPTION
AbstractList() 1.2 Constructs an empty (abstract) list.
modCount 1.2 Used by iterator to check for concurrent modifications of the list.
add() 1.2 Adds an element to the list.
addAll() 1.2 Adds a collection of elements to the list.
clear() 1.2 Clears all elements from the list.
equals() 1.2 Checks for equality with another object.
get() 1.2 Returns an element at a specific position.
hashCode() 1.2 Returns the computed hash code for a list.
indexOf() 1.2 Searches for an element within the list.
iterator() 1.2 Returns an object from the list that allows all of the list's elements
to be visited.
lastIndexOf() 1.2 Searches from the end of the list for an element.
listIterator() 1.2 Returns an object from the list that allows all of the list's elements
to be visited sequentially.
AbstractList Class
182

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×