The previous 14 chapters have presented the core EJB technology. What’s left is a grab bag of miscellaneous issues: how to solve particular design problems, how to work with particular kinds of databases, and topics of that nature.
Chapter 11
discusses the necessity of overriding the
Object.hashCode()
and
Object.equals()
methods in the primary key class
of an entity bean. With complex primary keys that have several
fields, overriding Object.equals()
is fairly
trivial. However, overriding
Object.hashCode()
is more
complicated, because an integer value that can serve as a suitable
hash code must be created from several fields.
One solution is to concatenate all the values into a
String
and use the String
object’s hashCode()
method to create a hash
code value for the whole primary key. The String
class has a decent hash code algorithm that generates a fairly
well-distributed and repeatable hash code value from any set of
characters.
The following code shows how to create such a hash code for a hypothetical primary key:
public class HypotheticalPrimaryKey implements java.io.Serializable { public int primary_id; public short secondary_id; public java.util.Date date; public String desc; public int hashCode() { StringBuffer strBuff = new StringBuffer(); strBuff.append(primary_id); strBuff.append(secondary_id); strBuff.append(date); strBuff.append(desc); String str = strBuff.toString(); int hashCode = str.hashCode(); return hashCode; } // the constructor, equals, and toString methods follow }
A StringBuffer
cuts down on the number of objects
created, since String
concatenation is expensive.
The code could be improved by saving the hash code in a private
variable and returning that value in subsequent method calls; this
way, the hash code is calculated only once in the life of the
instance.
A Hashtable
is designed to provide fast lookups by
binding an object to a key. Given any object’s key, looking up
the object in a hash table is a quick operation. For the lookup, the
key is converted to an integer value using the key’s
hashCode()
method.
Hash codes do not need to be unique, only well distributed. By
“well distributed” we mean that, given any two keys, the
chances are very good that the hash codes for the keys will be
different. A well-distributed hash code algorithm reduces, but does
not eliminate, the possibility that different keys evaluate to the
same hash code. When keys evaluate to the same hash code, they are
stored together and uniquely identified by their
equals()
methods. If you look up an object using a
key that evaluates to a hash code that is shared by several other
keys, the Hashtable
locates the group of objects
that have been stored with the same hash code; then it uses the
key’s equals()
method to determine which key
(and hence, which object) you want. (That’s why you have to
override the equals()
method in primary keys as
well as the hashCode()
method.) Therefore, the
emphasis in designing a good hash code algorithm is on producing
codes that are well distributed rather than unique. This strategy
allows you to design an index for associating keys with objects that
is easy to compute and therefore fast.