Page 1 sur 1

hashTable

MessagePublié: 30 Jan 2005 à 12:48
par oguruma
Code : Tout sélectionner
Private Class HashtableNode
   previous As HashtableNode
   next As HashtableNode
   value As Variant
   key As Variant
   Public Sub setPrevious(inPrevious As HashtableNode)
      Set Me.previous = inPrevious
   End Sub
   Public Function getPrevious() As HashtableNode
      Set Me.getPrevious = Me.previous
   End Function
   Public Sub setNext(inNext As HashtableNode)
      Set Me.next = inNext
   End Sub
   Public Function getNext() As HashtableNode
      Set Me.getNext = Me.next
   End Function
   Public Sub setKey(inKey As Variant)
      If Isobject(inKey) Then
         Set Me.key = inKey
      Else
         Me.key = inKey
      End If
   End Sub
   Public Function getKey() As Variant
      If Isobject(Me.key) Then
         Set Me.getKey = Me.key
      Else
         Me.getKey = Me.key
      End If
   End Function
   Public Function setValue(inValue As Variant)
      If Isobject(inValue) Then
         Set Me.value = inValue
      Else
         Me.value = inValue
      End If
   End Function
   Public Function getValue() As Variant
      If Isobject(Me.value) Then
         Set Me.getValue = Me.value
      Else
         Me.getValue = Me.value
      End If
   End Function
End Class
Public Class Hashtable
   ' A bad imitation of java.util.Hashtable...
   ' This is not a real Hashtable, as a real one uses hash values for each
   ' object passed to the table, for fast, indexed, access.
   ' The keys are NOT sorted.
   ' In LotusScript, there is no (?) way to get a hash of an object in a
   ' reasonable amount of time.
   ' This implementation may be slow on great number of key - value pairs,
   ' as it uses Vectors internally.
   ' A real Hashtable uses unique keys, but this class can handle multiple values with the same key,
   ' if the setMultipleKeys is set to true.
   
   multipleKeys As Integer
   elementCount As Long
   last As HashtableNode
   first As HashtableNode
   cachedNode As HashtableNode
   
   Public Sub setMultipleKeys(multiple As Integer)
   ' Set to true to get a Hashtable that can handle multiple values with the same key.
      Me.multipleKeys = multiple
   End Sub
   Public Function isMultipleKeysEnabled() As Integer
   ' Returns true if the Hashtable is enabled to handle multiple values with the same key
      isMultipleKeysEnabled = multipleKeys
   End Function
   Public Function size() As Long
   ' Returns the current number of keys in the Hashtable
      Me.size = Me.elementCount
   End Function
   Public Function isEmpty() As Integer
   ' Returns true if the number of the keys in the Hashtable is 0 (zero)
      Me.isEmpty = (Me.size = 0)
   End Function
   Public Function keys() As Enumeration
   ' Returns an Enumeration of all key elements in the Hashtable
      Set Me.keys =  New HashtableEnumeration(Me.first, True)
   End Function
   Public Function elements() As Enumeration
   ' Returns an Enumeration of all value elements in the Hashtable
      Set Me.elements =  New HashtableEnumeration(Me.first, False)
   End Function
   Private Function equals(element1 As Variant, element2 As Variant) As Variant
      equals = False
      If Isobject(element1) And Not Isobject(element2) Then Exit Function
      If Isobject(element1) Then
         If element1 Is element2 Then equals = True
      Else
         If element1 = element2 Then equals = True
      End If
   End Function
   Public Function contains(element As Variant) As Variant
   ' Returns true if the Hashtable contains the specified value
      Me.contains = False
      Dim node As HashtableNode
      Set node = first
      Do While Not node Is Nothing
         If Me.equals(element, node.getValue()) Then
            Me.contains = True
            Exit Do
         End If
         Set node = node.getNext()
      Loop
      If Not cachedNode Is Nothing Then Set cachedNode = node
   End Function
   Public Function containsKey(key As Variant) As Variant
   ' Returns true if the Hashtable contains the specified key
      Me.containsKey = False
      Dim node As HashtableNode
      Set node = first
      Do While Not node Is Nothing
         If Me.equals(key, node.getKey()) Then
            Me.containsKey = True
            Exit Do
         End If
         Set node = node.getNext()
      Loop
      If Not cachedNode Is Nothing Then Set cachedNode = node
   End Function
   Public Function get(key As Variant) As Variant
   ' Returns the value that corresponds to the specified key
   ' If the Hashtable has been enabled for values with the same keys, this function only returns the first value found.
      Set Me.get = Nothing
      If Not cachedNode Is Nothing Then
         If Isobject(key) And Isobject(cachedNode.getKey()) Then
            If key Is cachedNode.getKey() Then
               Set Me.get = cachedNode.getValue()
               Exit Function
            End If
         Elseif (Not Isobject(key)) And (Not Isobject(cachedNode.getKey())) Then
            If key = cachedNode.getKey() Then
               Me.get = cachedNode.getValue()
               Exit Function
            End If
         End If
      End If
      Dim node As HashtableNode
      Set node = first
      Do While Not node Is Nothing
         If Me.equals(key, node.getkey()) Then
            If Isobject(node.getValue()) Then
               Set Me.get = node.getValue()
            Else
               Me.get = node.getValue()
            End If
            Set Me.cachedNode = node
            Exit Function
         End If
         Set node = node.getNext()
      Loop
   End Function
   Public Function put(key As Variant, value As Variant) As Variant
      ' Sets a key - value pair. If the supplied already exists in the Hashtable,
      ' this function returns the value prior to the new one or Nothing,
      ' if the specified key was not found in the Hashtable.
      ' If not setMultipleKeys are enabled, this function replaces the value
      ' of the specified key (if found).
      Set Me.put = Nothing
      Dim node As New HashtableNode()
      Call node.setKey(key)
      Call node.setValue(value)
      
      If last Is Nothing Then   ' Empty hashtable
         Call node.setPrevious(Nothing)
         Call node.setNext(Nothing)
         Set last = node
         Set first = node
      Else
         Call last.setNext(node)
         Call node.setPrevious(last)
         Call node.setNext(Nothing)
      End If
      Set last = node
      Set cachedNode = node
      elementCount = elementCount + 1
   End Function                                 
   Public Function remove(key As Variant) As Variant
      ' Removes the specified key with its corresponding value,
      ' and returns the value removed or Nothing, if the key was not found.
      Set Me.remove = Nothing
      Dim node As HashtableNode
      Set node = first
      Do While Not node Is Nothing
         If Me.equals(key, node.getkey()) Then
            If Isobject(node.getValue()) Then
               Set Me.remove = node.getValue()
            Else
               Me.remove = node.getValue()
            End If
            Dim nextNode As HashtableNode
            Set nextNode = node.getNext()
            Dim previousNode As HashTableNode
            Set previousNode = node.getPrevious()
            If Not previousNode Is Nothing Then
               If Not nextNode Is Nothing Then
                  Call previousNode.setNext(nextNode)
                  Call nextNode.setPrevious(previousNode)
               End If
            Else
               If Not nextNode Is Nothing Then
                  Call nextNode.setPrevious(Nothing)
                  Set Me.first = nextNode
               Else
                  Call previousNode.setNext(Nothing)
                  Set Me.last = previousNode
               End If
            End If
            Set node = Nothing
            elementCount = elementCount - 1
            Exit Function
         End If
         Set node = node.getNext()
      Loop
   End Function
   Public Sub clear()
      ' Removes all keys and values in the Hashtable
      Dim node As HashtableNode
      Dim prevNode As HashtableNode
      Set node = first
      Do While Not node Is Nothing
         Call node.setKey(Nothing)
         Call node.setValue(Nothing)
         Call node.setPrevious(Nothing)
         Set prevNode = node
         Set node = prevNode.getNext()
         Call prevNode.setNext(Nothing)
         Set prevNode = Nothing
      Loop
      Me.elementCount = 0
   End Sub
   Public Function toString() As String
      ' Returns a String representation of this Hashtable.
      Dim s As String
      s = "{"
      Dim node As HashtableNode
      Set node = first
      Do While Not node Is Nothing
         s = s & Cstr(node.getKey()) & "=" & Cstr(node.getValue())
         If Not node.getNext() Is Nothing Then s = s & ", "
         Set node = node.getNext()
      Loop
      s = s & "}"
      toString = s
   End Function
   Public Function toArray() As Variant
      ' Returns a two dimensional array of the key-value pairs
      Dim a As Variant
      Redim a(elementCount - 1, 1)
      Dim i As Long
      Dim node As HashtableNode
      Set node = first
      Do While Not node Is Nothing
         If Isobject(node.getKey()) Then
            Set a(i, 0) = node.getKey()
         Else
            a(i, 0) = node.getKey()
         End If
         If Isobject(node.getValue()) Then
            Set a(i, 1) = node.getValue()
         Else
            a(i, 1) = node.getValue()
         End If
         i = i + 1
         Set node = node.getNext()
      Loop
      Me.toArray = a
   End Function
End Class
Public Class HashtableEnumeration As Enumeration
   isKey As Integer
   node As HashtableNode
   Public Sub new(inHashtableNode As HashtableNode, inIsKey As Integer)
      Set Me.node = inHashtableNode
      Me.isKey = inIsKey
   End Sub
   Public Function hasMoreElements() As Variant
      Me.hasMoreElements = False
      If node Is Nothing Then Exit Function
      Me.hasMoreElements = True
   End Function
   Public Function nextElement() As Variant
      If Not Me.hasMoreElements() Then Error 2000, "No more elements"
      If Me.isKey Then
         If Isobject(node.getKey()) Then
            Set Me.nextElement = node.getKey()
         Else
            Me.nextElement = node.getKey()
         End If
      Else
         If Isobject(node.getValue()) Then
            Set Me.nextElement = node.getValue()
         Else
            Me.nextElement = node.getValue()
         End If
      End If
      Set Me.node = node.getNext()
   End Function
End Class