|
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
22.12.1. HashtableEen Hashtable is specifiek ontworpen om efficient/snel elementen te kunnen toevoegen, verwijderen en opzoeken.
Het werkt door de op te zoeken key of de key van de toe te voegen entry via een hash functie om te zetten naar een hash code/waarde. Daarvoor gebruikt deze de van Object overgeërfde GetHashCode() method van het keytype. De door GetHashCode opgeleverde hash waarde is een getal die aangeeft op welke locatie ( ook wel bucket genoemd ) de entry wordt bewaard of wordt opgezocht. Dit getal ( key omgezet in hash code ) is een index van een tabel met buckets voor alle hash codes.
Als de hash function performant is, wat steeds de bedoeling is, kan het vinden of toevoegen van een element erg snel/efficient gebeuren. boven
22.12.2. Indien Fysieke Ook Logische Gelijkheid IsStel dat we van vak ( Square ) op een schaakbord ( board As HashTable ) wensen te weten welke stuk ( String ) zich op dit vak bevindt. We kunnen hiervoor de Square objecten mappen met de stukken door een HashTable te gebruiken. De Square objecten zijn de keys, de stukken zijn de values : Visual Basic 2010 Broncode Public Enum File FileA FileB End EnumPublic Enum Rank Rank1 Rank2 End EnumNamespace Example1 Public Class Square Public Sub New( ByVal file As File, ByVal rank As Rank) _File = file _Rank = rank End Sub Private ReadOnly _File As File Public ReadOnly Property File() As File Get File = _File End Get End Property Private ReadOnly _Rank As Rank Public ReadOnly Property Rank() As Rank Get Rank = _Rank End Get End Property End Class Class Client Public Shared Sub Main() Dim square1 As New Square(File.FileA, Rank.Rank1) Dim square2 As New Square(File.FileB, Rank.Rank1) Dim board As New Hashtable board.Add(square1, "R") board.Add(square2, "K") Console.WriteLine(board.Item(square1).ToString()) Console.WriteLine(board.Item(square2).ToString()) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output R
K Bovenstaande werkwijze functioneert goed indien elk vak op het bord slecht door één Square object wordt voorgesteld. Vergeet ook niet dat een Hashtable gebruik maakt van de hash code van het keyobject om de entry te kunnen plaatsen of opzoeken. Square erft van Object een GetHashCode over waarvan de opgeleverde hash code gebaseerd wordt op de referentie van het desbetreffende object. De Hashtable ( hier board ) maakt gebruik van deze hashcode om een Square object te plaatsen ( via Add ) of op te zoeken ( bijvoorbeeld via Item ) in de collectie. boven
22.12.3. Indien Logische Geen Fysieke Gelijkheid IsIndien er echter verschillende objecten zijn die hetzelfde vak voorstellen ( (1) en (2) ), zijn ze in dat opzicht logisch gelijk, volstaat bovenstaande constructie niet.
Voor meer informatie over fysieke versus logisch gelijkheid kan je terecht in de desbetreffende topics.
In onderstaand voorbeeld verwijzen zowel square1 als square3 naar vak "A1". De expressie board.Item(square3) die ons zou moeten opleveren welk stuk zich bevindt op vak "A1" levert echter niets ( Nothing ) op : Visual Basic 2010 Broncode Namespace Example2 Class Client Public Shared Sub Main() Dim square1 As New Example1. Square(File.FileA, Rank.Rank1) Dim square2 As New Example1. Square(File.FileB, Rank.Rank1) Dim square3 As New Example1. Square(File.FileA, Rank.Rank1) Dim board As New Hashtable board.Add(square1, "R") board.Add(square2, "K") Console.WriteLine(board.Item(square1).ToString()) Console.WriteLine(board.Item(square2).ToString()) Console.WriteLine(board.Item(square3) Is Nothing) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output R
K
True Bovenstaand ongewenst resultaat mag op zich niet verwonderen. square1 en square3 zijn immers fysiek verschillende objecten, met elke hun eigen hash code. En het is deze hash code die de Hashtable gebruikt om de objecten te identificeren ( plaatsen en opzoeken ). Als de Hashtable niet weet dat we ook via square3 stuk "R" wensen te vinden, of met andere woorden square1 en square3 logisch gelijk zijn, kan deze ook niet het gewenste verdrag vertonen. De Hashtable baseert zich op de hashcode van de keyobjecten om deze te identificeren ( en dus te vergelijken ), en deze zijn van onze twee objecten square1 en square3 nu immers verschillend : Visual Basic 2010 Broncode Namespace Example2 Class TestEqualityAndHashCode Public Shared Sub Main() Dim square1 As New Example1. Square(File.FileA, Rank.Rank1) Dim square3 As New Example1. Square(File.FileA, Rank.Rank1) Console.WriteLine(square1.Equals(square3)) Console.Write(square1.GetHashCode() = square3.GetHashCode()) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output False De van Object overgeërfde GetHashCode zal zich voor de op te leveren hash code baseren op de fysieke identiteit. boven
22.12.4. Object.Equals MethodOver het algemeen gesteld is het zo dat, indien logische gelijkheid van het keytype niet correspondeert met fysieke gelijkheid, er extra vereisten zijn voor dat keytype. We moeten door middel van de Equals implementatie aangeven welke objecten van dit keytype als logisch gelijk worden beschouwd, en door middel van de GetHashCode implementatie ervoor zorgen dat als logisch gelijk beschouwde objecten dan ook dezelfde hash code opleveren.
Aan onderstaand Square type moeten we dus enkel zaken toevoegen. Visual Basic 2010 Broncode Namespace Example3 Class Square Public Sub New( ByVal file As File, ByVal rank As Rank) _File = file _Rank = rank End Sub Private ReadOnly _File As File Public ReadOnly Property File() As File Get File = _File End Get End Property Private ReadOnly _Rank As Rank Public ReadOnly Property Rank() As Rank Get Rank = _Rank End Get End Property End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Om logische gelijkheid te definiëren kunnen we de van Object overgeërfde Equals implementatie herdefiniëren.
In dit geval beschouwen we twee Square objecten als logisch gelijk indien ze beide naar hetzelfde vak verwijzen, of beide dus dezelfde File en Rank waarde delen : Visual Basic 2010 Broncode Namespace Example3 Partial Class Square Public Overrides Function Equals( ByVal obj As Object) As Boolean If obj IsNot Nothing AndAlso TypeOf obj Is Square Then Dim other As Square = DirectCast(obj, Square) Equals = ( Me.Rank = other.Rank AndAlso Me.File = other.File) End If End Function End Class Public Class TestEquality Public Shared Sub Main() Dim square1 As New Square(File.FileA, Rank.Rank1) Dim square3 As New Square(File.FileA, Rank.Rank1) Console.Write(square1.Equals(square3)) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output True boven
22.12.5. Object.GetHashCode MethodOm er dan ook nog voor te zorgen dat Square objecten als key kunnen worden gebruikt, moeten we ook de van Object overgeërfde GetHashCode implementatie herdefiniëren.
Het belangrijkste voor deze implementatie is ervoor te zorgen dat logisch gelijke objecten steeds dezelfde hash code opleveren. Logischerwijs zal je GetHashCode implementatie hiervoor van dezelfde aspecten/properties/velden gebruik maken als je Equals implementatie, al is dit geen technische vereiste.
We zouden bijvoorbeeld in dit geval File en Rank kunnen combineren via de Xor operator : Visual Basic 2010 Broncode Namespace Example3 Partial Class Square Public Overrides Function GetHashCode() As Integer GetHashCode = File Xor Rank End Function End Class Public Class TestHashCode Public Shared Sub Main() Dim square1 As New Square(File.FileA, Rank.Rank1) Dim square3 As New Square(File.FileA, Rank.Rank1) Console.Write(square1.GetHashCode() = square3.GetHashCode()) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output True Waarom in dergelijke situatie vaak de Xor operator wordt gebruikt, wordt verderop behandeld. Alvast is duidelijk dat twee objecten met dezelfde File en Rank waarde nu ook dezelfde hash code zullen opleveren, wat uiteindelijk hetgene is wat de GetHashCode moet doen.
Nu kunnen we wel aan de hand van square3, net als aan de hand van square1 het stuk "R" terugvinden : Visual Basic 2010 Broncode Namespace Example3 Class Client Public Shared Sub Main() Dim square1 As New Square(File.FileA, Rank.Rank1) Dim square2 As New Square(File.FileB, Rank.Rank1) Dim square3 As New Square(File.FileA, Rank.Rank1) Dim board As New Hashtable board.Add(square1, "R") board.Add(square2, "K") Console.WriteLine(board.Item(square1).ToString()) Console.WriteLine(board.Item(square2).ToString()) Console.WriteLine(board.Item(square3).ToString()) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output R
K
R
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
|