VB .NET - Usando a coleção genérica Dictionary


Você conhece a classe genérica Dictionary ? Se não conhece deixe-me apresentá-la...

A classe Dictionary representa uma coleção de chaves e valores. É uma coleção do tipo chave/valor e implementa  a interface IDictionary que possui duas coleções no seu interior uma para guardar a chave e outra para guardar o valor.

A sintaxe é a seguinte:

Dictionary (Of (TKey,TValue))

esta presente no namespace :  System.Collections.Generic

no assembly : mscorlib (in mscorlib.dll)

onde:

TKey - representa o tipo da chave no dicionário;
TValue - representa o tipo do valor no dicionário;

A classe genérica Dictionary é uma classe que mapeia um conjunto de chaves, as quais podem ser de qualquer tipo, para um conjunto de valores, que também podem ser de qualquer tipo sendo que os tipos da chave e o valor não precisam ser idênticos.

Podemos dizer que a coleção Dictionary é uma coleção genérica de tipo que é informado no momento de definir a coleção. É uma coleção do tipo chave/valor onde a chave faz o papel do índice na coleção.

Cada inclusão de um elemento no dicionário consiste de um valor e sua chave associada. O retorno de um valor a partir de sua chave tem um bom desempenho pois a classe Dictionary é implementada como um hashtable.

Obs: No Visual Basic tínhamos o objeto Dictionary que não apresentava um bom desempenho já a classe Dictionary do VB .NET utiliza tabelas de hash internas e apresenta um bom desempenho.

Em todos os exemplos deste artigo eu estou usando o Visual Basic 2008 Express Edition.

Vejamos a seguir algumas das propriedades e características da classe Dictionary:

Para criar um objeto dictionary você deve definir um chave seguida por um valor. O primeiro indica a chave do elemento que deverá ser incluído e o segundo representa o valor que a chave deverá possuir.

Para incluir elementos em um objeto dictionary devemos usar o método Add que calcula o valor do código do hash da chave e então armazena os dados no hash.

Vejamos a seguir um exemplo de como criar um objeto dictionary no Visual Basic 2008:

No código acima estamos criando um objeto Dictionary com chave do tipo String e valores do tipo Integer e e usando o método Add para incluir 6 chaves e valores.

Se você incluir uma chave que já existe no dicionário irá ocorrer uma exceção, para evitar isso você pode verificar se uma chave já existe através do método ContainsKey.

A seguir temos um exemplo que usar o método ContainsKey para verificar se uma chave já existe:

   Public Sub UsandoContainsKey()

        'Declara um novo Dictionary  de chave 
        'do tipo string e valores integer
        Dim frutas As New Dictionary(Of String, Integer)

        ' Inclui duas chaves : banana e maça
        ListBox1.Items.Add("Incluindo as chaves : banana(15) e maça(7)")
        frutas.Add("banana", 7)
        frutas.Add("maça", 15)

        ' Verficia se uma chave já existe
        If frutas.ContainsKey("banana") Then
            ' Escreve um valor para a chave
            ListBox1.Items.Add("A chave banana já existe")
            Dim valor As Integer = frutas.Item("banana")
            ListBox1.Items.Add("Valor = " & valor)
        End If

        ' Verifica se a chave ja existe
        If frutas.ContainsKey("maça") Then
            ListBox1.Items.Add("A chave maça já existe")
            Dim valor As Integer = frutas.Item("maça")
            ListBox1.Items.Add("Valor = " & valor)
        End If

        If Not frutas.ContainsKey("abacaxi") Then
            ListBox1.Items.Add("A chave abacaxi NÃO existe")
        End If
    End Sub

Criamos um Dictionary identificado pelo nome frutas e incluímos
duas chaves e dois valores;

A seguir usamos o método ContainsKey para verificar se uma chave
já existe.

Você também pode armazenar o resultado de uma verificação usando ContainsKey em uma variável boolean e testar a variável usando os operadores = (igual) e <> (diferente).

Os principais métodos da classe Dictionary são:

Nome Descrição
Add Inclui uma chave e um valor especificados no dicionário.
Clear Remove todas as chaves e valores do dicionário.
ContainsKey Determina se o dicionário contém uma chave especifica.
ContainsValue Determina se o dicionário contém um valor específico.
Equals Determina se o objeto especificado é igual a objeto atual.
GetEnumerator Retorna uma enumeração que itera através do dicionário.
Remove Remove o valor com a chave especificada do dicionário.
TryGetValue Obtém o valor associado com a chave especificada.

As principais propriedades da Classe Dictionary são:

Nome Descrição
Count Obtêm o número do par chave/valor contido em um dicionário.
Item Obtêm ou define o valor associado a uma chave específica;
Keys Obtêm uma coleção contento as chaves no dicionário;
Values Obtêm uma coleção contendo os valores no dicionário.

Para percorrer um objeto Dictionary podemos usar um loop For Each para percorrer a estrutura KeyValuePair no dicionário. No corpo do laço For/Each você pode acessar os valores da chave e valor de KeyValuePair. Abaixo temos um exemplo:

 Public Sub percorreDictionary()
         ListBox1.Items.Clear()

        ' Cria um dictionary e inclui 8 chaves do tipo string
        Dim times As New Dictionary(Of String, Integer)
        times.Add("Palmeiras", 54)
        times.Add("Santos", 41)
        times.Add("Flamento", 49)
        times.Add("Atlético", 50)
        times.Add("Internacional", 41)
        times.Add("Goiás", 48)
        times.Add("Cruzeiro", 45)
        times.Add("Gremio", 46)

        ' Faz um Loop sobre as entradas do dicionário
        Dim par As KeyValuePair(Of String, Integer)
        For Each par In times
            ' Exibe a chave e os valores
            ListBox1.Items.Add(par.Key & "-" & par.Value)
        Next

    End Sub

Podemos listar o conteúdo de um objeto do tipo DIctionary a partir de uma coleção List de chaves em um  Dictionary. Cada instância de Dictionary possui uma propriedade Get com o identificador Keys. Você pode acessar esta coleção e passá-la para o construtor da Lista de chaves. As chaves possuem o mesmo tipo que o Dictionary de origem:

 Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        ListBox1.Items.Clear()
        ' Cria 5 chaves e valores no dicionário
        Dim carros As New Dictionary(Of String, Integer)
        carros.Add("gol", 12)
        carros.Add("fiesta", 11)
        carros.Add("polo", 10)
        carros.Add("palio", -21)
        carros.Add("astra", -8)

        ' Põe a chave em uma lista de strings
        Dim lista As New List(Of String)(carros.Keys)

        ' Percorre a lista
        Dim str As String
        For Each str In lista
            ' Imprime a string e também o item 
            ListBox1.Items.Add(str & " - " & carros.Item(str))
        Next
    End Sub

O resultado obtido é o seguinte:

Neste exemplo criamos um dicionário e em seguida colocamos a chave em uma lista de strings. A seguir percorremos a lista para exibir os itens.

Para remover um item do Dictionary usamos o método Remove.  Você precisa passar um parâmetro para este método indicando qual a chave você deseja remover do dicionário. Se você tentar remover  uma chave que não existe irá ocorrer uma exceção.

O método ContaisValue retorna um valor booleano que informa se qualquer valor no dicionário é igual ao argumento que você forneceu.

No exemplo abaixo usamos o método ContaisValue para verificar se um valor existe no dicionário e também o método Remove removendo duas chaves existentes:

 Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        ListBox1.Items.Clear()
        ' Cria um novo dicionario com 6 chaves
        Dim flores As New Dictionary(Of String, Integer)
        flores.Add("rosa", 20)
        flores.Add("cravo", 21)
        flores.Add("tulipa", 31)
        flores.Add("adália", 41)
        flores.Add("margarida", 61)
        flores.Add("orquídea", 91)

        ' Verifica se o valor 21 esta no dicionario
        If flores.ContainsValue(21) Then
            ListBox1.Items.Add("O valor 21 esta no dicionário.")
            ListBox1.Items.Add("O item é = " & flores.Item("tulipa"))
        End If

        ' Remove duas chaves: Remove
        flores.Remove("tulipa")
        flores.Remove("margarida")

        ListBox1.Items.Add("Removidas as chaves :  tulipa e margarida.")

        ' Faz um Loop sobre as entradas do dicionário
        Dim par As KeyValuePair(Of String, Integer)
        For Each par In flores
            ' Exibe a chave e os valores
            ListBox1.Items.Add("Valores e chaves existentes.")
            ListBox1.Items.Add(par.Key & "-" & par.Value)
        Next

    End Sub

Executando este código iremos obter:

Para contar o número de entradas em um dicionário você pode usar a propriedade Count. A sintaxe usada é :  dictionary.Count.

Veja exemplo abaixo onde criamos um dicionário com o nome legumes e efetuamos 3 contagens após realizar algumas operações no dicionário:

Private Sub dictionaryCount()

ListBox1.Items.Clear()

Dim legumes As New Dictionary(Of String, Integer)()

legumes.Add("batata", 1)

legumes.Add("cenoura", 4)

legumes.Add("repolho", 6)

legumes.Add("beterraba", 3)

' Copia as chaves

Dim contador1 As Integer = legumes.Count

' Remove uma chave.

legumes.Remove("cenoura")

' conta as chaves novamente

Dim contador2 As Integer = legumes.Count

' Limpa o conte£do do dicion rio

legumes.Clear()

' conta as chaves novamente

Dim contador3 As Integer = legumes.Count

' Exibe os valores obtidos

ListBox1.Items.Add("contador1=" & contador1)

ListBox1.Items.Add("contador2=" & contador2)

ListBox1.Items.Add("contador3=" & contador3)

End Sub

Se você necessitar copiar todo o conteúdo de um dicionário, para fazer isso basta declarar uma nova referência a um objeto Dictionary e usar o construtor Copy e passar no o dicionário que você deseja copiar como parâmetro.

A seguir temos um exemplo que copia um dicionário mamiferos para um novo objeto Dictionary , em seguida inclui mais uma chave no primeiro dicionário e a seguir lista os dois dicionários:

Private Sub dictionaryCopy()

ListBox1.Items.Clear()

Dim mamiferos As New Dictionary(Of String, Integer)()

mamiferos.Add("cachoro", 1)

mamiferos.Add("elefante", 9)

mamiferos.Add("tigre", 10)

' Copia o Dicion rio para o segundo objeto

Dim copy As New Dictionary(Of String, Integer)(mamiferos)

' Altera o primeiro dicion rio (Isso nÆo causa altera‡äes na copia)

mamiferos.Add("tubarÆo", 4)

' Exibe o primeiro dicion rio

ListBox1.Items.Add("--- Dictionary 1 ---")

For Each par In mamiferos

   ListBox1.Items.Add(par)

Next

 

' Exibe o seguind dicion rio

ListBox1.Items.Add("--- Dictionary 2 ---")

For Each par In copy

   ListBox1.Items.Add(par)

Next

 

End Sub

As coleções são muito úteis na programação moderna e podem ajudar muito o desenvolvedor. Compreender o seu funcionamento correto é muito importante.

Pegue o projeto completo aqui : Dictonary.zip

Eu sei é apenas VB .NET, mas eu gosto...

referências:


José Carlos Macoratti