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 Signature | From |
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}:
STANDARD_HASH
- use object hashCode()
and equals()
comparison
IDENTITY_COMP
- use object hashCode()
and ==
comparison
IDENTITY_HASH
- use System.identityHashCode()
and ==
comparison
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 String
s which have been intern
ed).
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.