Type-specific hash map collections. The classes in this package are basically equivalent to somewhat simplified and type-specific versions of the standard java.util.Hashmap or newer java.util.HashMap class. They generally use the method names defined by HashMap as opposed to the older Hashmap names. The standard public access methods in these classes are as follows:

Method SignatureFrom
type2 add(type1, type2)implementation class
void clear(){@link com.sosnoski.util.hashmap.PrimitiveKeyBase} or {@link com.sosnoski.util.hashmap.ObjectKeyBase}
Object clone()implementation class
boolean containsKey(type1)implementation class
void ensureCapacity(int){@link com.sosnoski.util.PrimitiveHashBase} or {@link com.sosnoski.util.ObjectHashBase}
type2 get(type1)implementation class
Iterator iterator(){@link com.sosnoski.util.hashmap.ObjectKeyBase} (not implemented for primitive keys)
type2 remove(type1)implementation class
int size(){@link com.sosnoski.util.PrimitiveHashBase} or {@link com.sosnoski.util.ObjectHashBase}
Iterator valueIterator()implementation class (not implemented for primitive values)

As with HashMap, the access methods are unsynchronized for best performance. The user program must implement appropriate locking if multiple threads need to access an instance of these classes while that instance may be modified.

Maps may use either a primitive type or an object type as both keys and values. Two separate base classes are defined for different classes of maps: {@link com.sosnoski.util.hashmap.PrimitiveKeyBase} for maps with keys of primitive types, and {@link com.sosnoski.util.hashmap.ObjectKeyBase} for maps with object keys.

Collections of object types may be configured to use any of three possible combinations of hash method and key comparison techniques. The choice is determined by an optional tech parameter to the constructor, with the following values inherited from {@link com.sosnoski.util.ObjectHashBase}:

In testing with the Sun Java 1.3.1 JVM System.identityHashCode() turns out to be very slow in comparison to a typical hashCode() implementation, so be careful of using the IDENTITY_HASH option. IDENTITY_COMP is always faster than STANDARD_HASH, though, so it's a good choice when you know that objects are unique (such as Strings which have been interned).

To define a hash map of a new type, derive from the appropriate base class and define the necessary implementation methods. A pair of useful hash map classes which can be used as model code for new variations are included in the package, {@link com.sosnoski.util.hashmap.IntStringHashMap} (mapping int keys to String values) and {@link com.sosnoski.util.hashmap.StringIntHashMap} (mapping String keys to int values). The source for these can be copied and renamed as appropriate, then text substitutions used to change the types (with some care in the case of "int", since this type is used internally as well as for the keys or values).

Before launching into this, you may want to look at the {@link com.sosnoski.util.hashset} package, which provides a simpler view based on much of the same underlying code. That package also contains a few more examples, including one for double primitive keys.

Defining new hash map classes is generally not too useful for different types of object keys, since none of the methods return keys. It is necessary for working with primitive types as either keys or values (other than the combinations supplied), though, and can also be worthwhile for different object value types.

If you work with primitive types as keys you'll also need to define a hashing function (the computeSlot method in these classes). Selecting a good hash computation method for your data requires considerable research. The methods used in the provided code have not been subjected to any serious testing and may be flawed by poor distributions, which results in higher overhead for operations on the set. If you're using hash-based collections heavily, make sure the hashing method you choose works well with your data.

Hash maps of both object and primitive types use considerably less memory than the corresponding standard Java library implementations, so a good approach to take when using these collections in high-performance applications is to be generous in setting the initial size for the tables. It may also improve performance if you lower the fill parameter value, so that the tables are expanded more often.