按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
The MSDN documentation for Object。GetHashCode defines the GetHashCode() method as follows
(http://msdn2。microsoft。/en…us/library/system。object。gethashcode(VS。90)。aspx):
The GetHashCode method can be overridden by a derived type。 Value types must over
ride this method to provide a hash function that is appropriate for that type and to
provide a useful distribution in a hash table。 For best results; the hash code must be
based on the value of an instance field or property instead of a static field or property。
Objects used as a key in a Hashtable object must also override the GetHashCode method
because those objects must generate their own hash code。 If an object used as a key does
not provide a useful implementation of GetHashCode; you can specify a hash code
provider when the Hashtable object is constructed。
But what does this actually mean? The purpose of GetHashCode() is to identify the object in
a collection of other objects using a hash code。 Imagine creating a table of same…type instances。
The situation occurs when you create a collection and store a bunch of instances in the collec
tion。 With the GetHashCode() method; you can generally separate each instance from each other。
I say “generally” because GetHashCode() is an approximation。 To verify if one object instance
equals another; the Equals() method needs to be implemented。
…………………………………………………………Page 302……………………………………………………………
280 CH AP T E R 1 0 ■ L E A R N I N G A B OU T P E R S IS TE N CE
Implementing a hash code is best delegated to a helper class that does the heavy lifting。
The book Effective Java Programming Language Guide by Joshua Bloch (Prentice…Hall; 2001)
outlines a robust technique。 Basically; you store some constant nonzero value; such as 17; in
a variable。 Then; for each data member of the type; perform a mathematical operation that
results in Integer values that are successively multiplied and added; where the operation is
specific to the type and defined as follows:
o Boolean: If true return 0; otherwise return 1。
o Byte; Char; Short; or Integer: Return the value of the type。
o Long: Return CInt(value Xor (value 》》 &H20))。 &H20 is the hexadecimal for 32。
o Single: Return Convert。ToInt32 of the value。
o Object: Return the value generated by calling Object。GetHashCode()。
o Array : Iterate and treat each element individually。
The rules are implemented in a class called HashCodeAutomater。 The following source code
is an implementation in an abbreviated form:
Public Class HashCodeAutomater
Private Readonly _constant As Integer
Private _runningTotal As Integer
Public Sub New()
_constant = &H25
_runningTotal = &H11
End Sub
Public Function AppendSuper(ByVal superHashCode As Integer) As HashCodeAutomater
_runningTotal = ((_runningTotal * _constant) + superHashCode)
Return Me
End Function
Public Function Append(ByVal obj As Object) As HashCodeAutomater
If (obj Is Nothing) Then
Me。_runningTotal = (Me。_runningTotal * Me。_constant)
ElseIf Not obj。GetType。IsArray Then
Me。_runningTotal = ((Me。_runningTotal * Me。_constant) + obj。GetHashCode)
ElseIf TypeOf obj Is Long() Then
Me。Append(DirectCast(obj; Long()))
ElseIf TypeOf obj Is Integer() Then
Me。Append(DirectCast(obj; Integer()))
ElseIf TypeOf obj Is Short() Then
Me。Append(DirectCast(obj; Short()))
ElseIf TypeOf obj Is Char() Then
Me。Append(DirectCast(obj; Char()))
…………………………………………………………Page 303……………………………………………………………
CH A PT E R 1 0 ■ L E A R N I N G A B O U T P E R S IS T E N CE 281
ElseIf TypeOf obj Is Byte() Then
Me。Append(DirectCast(obj; Byte()))
ElseIf TypeOf obj Is Double() Then
Me。Append(DirectCast(obj; Double()))
ElseIf TypeOf obj Is Single() Then
Me。Append(DirectCast(obj; Single()))
ElseIf TypeOf obj Is Boolean() Then
Me。Append(DirectCast(obj; Boolean()))
Else
Me。Append(DirectCast(obj; Object()))
End If
Return Me
End Function
Public Function Append(ByVal array As Long()) As HashCodeAutomater
If (array Is Nothing) Then
Me。_runningTotal = (Me。_runningTotal * Me。_constant)
Else
Dim i As Integer
For i = 0 To array。Length 1
Me。Append(array(i))
Next i
End If
Return Me
End Function
Public Function Append(ByVal value As Long) As HashCodeAutomater
Me。_runningTotal = _
((Me。_runningTotal * Me。_constant) + CInt((value Xor (value 》》 &H20))))
Return Me
End Function
Public Function ToHashCode() As Integer
Return _runningTotal
End Function
End Class
The different implementations of the Append() method belong to a single grouping for a
single data type; Long。 For example; there is an Append() method that accepts a Long and a Long
array。 The full implementation of HashCodeAutomater would have an Append() method for Short
and Short array; and all the other data types。 There is no specific group implementation for the
String type; because it is treated like an object that has its own hash…code calculation
implementation。
Notice in the implementations of the Append() methods how a calculation is performed
and then added to the data member _runningTotal。 The return value is a Me reference; so that
the methods can be chained together。 This allows a client to use the HashCodeAutomater class;
as the following GetHashCode() implementation demonstrates:
…………………………………………………………Page 304……………………………………………………………
282 CH AP T E R 1 0 ■ L E A R N I N G A B OU T P E R S IS TE N CE
Class HashcodeExample
Public value As Integer
Public buffer As String
Public Sub New (ByVal val As Integer; ByVal buf As String)
value = val
buffer = buf
End Sub
Public Overrides Function GetHashCode() As Integer
Return New HashCodeAutomater()
。Append(value)
。Append(buffer)。toHashCode()
End Function
End Class
The implementation of HashcodeExample has two data members: value and buffer。 The
two data members make up the class’s state。 Not all data members are used when calculating
a class instance’s hash…code value。 For example; if HashcodeExample had a data member that
referenced a database connection; it should not be used when calculating the hash code; because
the database connection is the type used to get the state and does not influence the state—it is
a means to an end。
Implementing Equals()
Once the GetHashCode() method has been implemented; the Equals() method can be
implemented:
Public Overrides Function Equals(ByVal obj As Object) As Boolean
If TypeOf(obj) Is HashCodeExam