Package net.walend.collection

This package contains a collection kit.


Interface Summary
AbstractHashMap.Entry Sublcass this abstract class and override newEntry to use specialized Entries.
Collection This interface is the root interface in the javasupport.collection package.
HasState Classes of objects that have an internal state should implement this interface as a better alternative to overriding equals().
Identitor This interface proscribes utility methods for working with objects in collections.
Immutable If a class is declared final, has no mutator methods and no visible variable members, it should implement this marker interface.
List An ordered Collection that gives the programmer precise control over where Objects in the list exit.
Map A container that maps keys to values.
MutableCollection Use this interface for changable Collections of Objects.
MutableList add() appends the object to the end of the list.
MutableMap MutableMap adds mutator methods to Map.
MutableSet This class is a Collection that contains Objects so that each Object exists at most once in the set.
Set This class is a Collection that contains Objects so that no more than one of each Object exists in the Set.

Class Summary
AbstractArrayList An implementation of List backed by an array.
AbstractHashMap This class is a hash table based implementation of the net.walend.collection.Map interface, based very heavily on the java.util.HashMap class by Josh Bloch and ultimately Arthur van Hoff.
AbstractHashSet This class implements the net.walend.collection.Set interface, based very heavily on the java.util.HashSet class by Josh Bloch.
ArrayList This implementation of List is built on top of an array.
DefaultIdentitor This class implements Identitor using an object's own equals() and hashCode() methods.
HashMap This is an immutable implementation of Map
HashSet This implementation of Set is built on top of a Map.
ImmutableIteratorWrapper Use this class to block Iterator's remove method in Immutable classes.
MultiIterator An implementation of Iterator built up from other iterators.
MutableArrayList add() appends the object to the end of the list.
SoftHashMap This MutableHashMap's values are held by soft references which may disapear if memory gets short.

Package net.walend.collection Description

This package contains a collection kit.

The java.util collections are wonderful. I've found them somewhat difficult to use while working with persistent objects, however, because they override equals() and hashcode() themselves. Does a Set persisted in a database equal an active version of that same set in memory if you add an object to the set in memory? It's supposed to be the same set, but the contents don't match anymore. I don't know what the right answer is, but overriding equals makes persisting Collections more difficult.

So I created this kit of objects that leaves equals and hashcode alone, and supplies a sameContentsAs method.

The kit's base interface is net.walend.Collection. This interface proscribes methods for querying the Collection for its contents.

Each Collection's constructor has an Identitor, which supplies the Collection with equals and hashCode methods to use in that collection. The default Identitor uses the collected object's equals() and hashcode() methods. Collections which enforce some order have constructors with a java.util.Comparator, which supplies a sorting method.

Naming conventions

The base interface of a collection has a simple name that defines that collection. For example, net.walend.Set. An implementation has a name that describes that implementation, followed by the simple name. For example, net.walend.HashSet. The interface that defines the mutators has the "mutable" prefix: net.walend.MutableSet. An implementation of that interface also gets the "mutable" prefix: net.walend.MutableHashSet. If the collection is of specific objects, it has an appropriate postfix: net.walend.MutableHashSetOfStrings.

Accessor methods for these collections are in one interface. Mutators are in a separate subinterface with the unsubtle prefix Mutable. This design decision prevents the unwieldy hack of throwing UnsupporedOperationExceptions for immutable collections. Code that calls mutators on immutable objects simply gets compile time errors instead of surprising uncaught RuntimeExceptions. That vastly simplifies writing thready code; if an object is immutable, the code that uses that object need not synchronize on it. Immutable classes are final and further implement the Immutable marker interface. The test kit supplies a test to insure this feature. Abstract superclasses of the interfaces prevent having to clone code between two classes.

Immutable collections should implement two constructors. The first should take another net.walend.collection.Collection. The constructor should perform a shallow copy of the collection. The second should take a java.util.Collection and perform the same shallow copy. The copied immutable collections must use the same Identitor.

Mutable collections should implement six (!) constructors. The first should perform a shallow copy of another net.walend.collection.Collection. The second should perform a shallow copy of a java.util.Collection. The third should have no arguments and produce an empty collection with default storage size of 7. The forth should take int parameters as needed and produce an empty collection with default storage size built from those parameters. A fifth and sixth constructor should create empty collections with a given Identitor implementation.

Class diagram of the Collection hierarchy.

These patterns show in the Collection class hierarchy's Set implementers. MutableSet inherits from Set. AbstractHashSet implements Set, and implements the methods in MutableSet as protected methods. MutableHashSet opens up those protected methods as public methods to implement MutableSet. HashSet does not, is final, and implements the Immutable interface.

Class diagram of the Map hierarchy.

I repeat the patterns in the Map hierarchy.

The main interfaces in net.walend.collection currently include Collection, for bags, Set, for sets, and Map, for maps. The package currently provides implementations of Set, MutableSet, Map, and MutableMap.

The package also provides a utility interface, HasState, and a utility class, MutiIterator.

Objects with internal state can implement the HasState interface as an alternative to overriding equals() (and being forced to override hashcode()). HasState provides one method, sameStateAs(), which should compare the internal states of the two objects to determine if the two states are the same. equals() can then be used to determine if the two references are the same object.

Collections have the same state if they have the same contents and use equal Identitor.

MultiIterator is a utility class for iterating through many Iterators. It holds an Iterator of Iterators. When one Iterator has no more objects, the MultiIterator works through the next Iterator.

Copyright (c) 2000, 2001, David Walend