Enlaces e información
Comenta lo que creas oportuno.
Hashtables con clave compleja
Un hashtable es un tipo de coleccion que relaciona un valor Clave con un Valor. Estos pares se almacenan en la coleccion basados en un valor Hash de la clave. Dicho valor Hash tiene las siguientes caracteristicas:
- Es un entero de 32 bits.
- Debe ser ?nico para cada Clave.
- No debe de variar en la vida del Hashtable.
- Si dos objetos representan el mismo valor, deben devolver el mismo Hash.
- Y debe tener un valor cuya distribucion variable para todos los hashes del Hashtable sea lo mas uniforme posible.
Teniendo en cuenta esto, todos los objetos de .NET ofrecen una funcion que devuelve el codigo hash propio, que es el que utiliza el Hashtable para ordenar por la clave.
La implementacion por defecto no garantiza todas las caracteristicas anteriormente comentadas que deberia tener todo c?digo hash, es por ello que es recomendable implementar un generador de hash propio siempre que la clase vaya a ser utilizada como clave dentro de un Hashtable.
Esto es sobre todo de vital importancia cuando la clave es una clave compuesta de 2 valores. Por ejemplo, supongamos que la manera de trabajar de un usuario es que debe visitar a un cliente cada d?a y en cada visita debe rellenar un factura. Queremos guardar para cada dia y cliente (esta seria la clave), una factura (este es el valor).
Lo primero: es importante definir que la clave no va a ser modificada durante la vida del Hashtable. Una vez creada la hashtable, no podemos decir que tal dia se visitara a otro cliente distinto.
Lo segundo: Codificamos la clase clave:
Protected m_objCliente As CCliente
Public ReadOnly Property Cliente() As CCliente
Get
Return m_objCliente
End Get
End PropertyProtected m_dFecha As Date
Public ReadOnly Property Fecha() As Date
Get
Return m_dFecha
End Get
End Property
Public Sub New(ByVal objCliente As CCliente, ByVal dFecha As Date)
m_objCliente = objCliente
m_dFecha = dFecha
End Sub
…
En Clase
Esta clase define la clave del hashtable. Pero debemos de implementar nuestro propio HashCode ya que si no lo hacemos el Hashtable no funcionaria. La implementacion por defecto del HashCode de la clase anterior devuelve una referencia a la instancia. Lo que va a pasar es que cuando insertemos la clave no podremos crear un objeto clave nuevo igual para buscar ya que el nuevo objeto tendra un valor de instancia nuevo y por ende un codigo Hash diferente.
Aqui es donde radica la dificultad. Debemos de generar un HashCode que nos asegure que sea unico y que este bien distribuido en todo el Hashtable.
Return m_dFecha.GetHashCode * NumClientes + m_objCliente.Codigo
End Function
Si el Codigo del cliente fuese desde 0 a NumClientes y que se metiesen todos los clientes en el Hashtable conseguiriamos una distribucion uniforme del c?digo hash en el Hashtable.
Por otro lado conviene tambien redefinir la funcion Equals en base los valores que contiene y asi cumplir la norma que impone que dos instancias de un objeto son iguales para el Hashtable en el momento que representen la misma clave:
Dim objCliente As CHashtableKey = obj
Return (m_objCliente.Codigo = objCliente.Cliente.Codigo) And (m_dFecha = obj.Fecha)
End Function
Hay mucho que decir acerca de este tema:
- ?Nos fiamos de los c?digos hash de los tipos predefinidos?
- ?Hasta que punto queda bien definido el hash devuelto por un objeto compuesto para todos los casos en que se utilice?
- En el ejemplo: ?Nos podemos fiar del hash devuelto por la fecha para generar nuestro propio hash?
etc, etc.
i am going to tell my friends about this site - it’s just perfect!