C# - Apresentando a classe Hashtable


 Neste artigo vou apresentar os conceitos básicos sobre a classe HashTable da linguagem C#.

O Microsoft .NET Framework fornece várias classes que colecionam elementos juntos de maneiras especializadas. Estas são as classes de coleção e existem no namespace System.Collections e namespaces subsequentes.

Talvez a mais conhecidas sejam as classes Array e ArrayList.

Os tipos Array e ArrayList fornecem uma forma de mapear um índice inteiro a um elemento. você fornecer um índice inteiro dentro de colchetes (por exemplo, [4]), e você recebe de volta o elemento no índice 4 (que é na verdade o quinto elemento).

No entanto, às vezes você pode querer fornecer um mapeamento onde o tipo que você deseja mapear não é um int, mas sim algum outro tipo, tal como uma string, um double ou Time.

A classe Hashtable oferece essa funcionalidade, mantendo internamente duas matrizes de objeto, uma para as chaves a partir da qual você está mapeando, e, uma para os valores que você está mapeando.

Quando você insere um par chave/valor em um Hashtable, ela rastreia automaticamente qual chave pertence a qual valor e permite recuperar o valor que está associado com uma chave especificada rápida e facilmente.

Assim um Hashtable é como um recipiente utilizado para armazenar dados em pares de chave/valor  onde as chaves são usadas como índice e ajudam a localizar os valores rapidamente.

Dessa forma a classe Hashtable representa uma coleção de pares chave/valor que são organizados com base no código hash da chave.

Nota : As classes básicas de coleções aceitam, mantém e retornam seus elementos como objetos, isto é, o tipo de elemento de uma classe de coleção é um objeto. Para entender as implicações disto, é útil para contrastar um array de variáveis int (int é um tipo de valor) com um array de objetos (object é um tipo de referência). Como int é um tipo de valor, uma série de variáveis int detém seus valores int diretamente, como mostrado na figura a seguir:



Agora, considere o caso quando o array é uma matriz de objetos. Você ainda pode adicionar valores inteiros a essa matriz. (Na verdade, você pode adicionar valores de qualquer tipo a ele.) Quando você adiciona um valor inteiro, ele é 'embalado' automaticamente, e o elemento da matriz (uma referência de objeto) refere-se à cópia em caixa do valor inteiro. Isto é ilustrado na figura abaixo seguinte:

O tipo de elemento de todas as classes de coleções é um objeto. isso significa que quando você inserir um valor em uma coleção, ele é embalado/encaixotado, e quando você remover um valor de uma coleção, você deve desencaixotá-lo, ou seja retornar ao seu tipo original, usando um cast.

Nota:  Ao trabalhar com a classe Hastable tenha em mente que a ordenação dos elementos na coleção é independente da ordem na qual ele entrou na tabela. A classe emprega seu próprio algoritmo hash para ordenar de forma eficiente os pares chave/valor da coleção.

Existem algumas consequências importantes da concepção da classe Hashtable:

1-) No exemplo abaixo temos um exemplo que associa as idades de algumas pessoas com seus nomes e a seguir exibe a informação:

using System;
using System.Collections;
namespace HashTable
{
    class Program
    {
        static void Main(string[] args)
        {
            Hashtable idades = new Hashtable();
            //preenche uma HashTable
            idades["Macoratti"] = 48;
            idades["Miriam"] = 39;
            idades["Janice"] = 21;
            idades["Jefferson"] = 23;
            idades["Yuri"] = 21;
            idades["Bianca"] = 21;
            // iterando usando a instrução foreach 
            // O iterador gera um objeto DictionaryEntry contendo o par key/value
            foreach (DictionaryEntry element in idades)
            {
               //obtém os valores da HashTable usando Key e Value
                string nome = (string)element.Key;
                int idade = (int)element.Value;
                //exibe os valores da HashTable
                Console.WriteLine("Nome: {0}, Idade: {1}", nome, idade);
            }
        }
    }
}

2-) Outro exemplo que associa valores e nomes de algumas cidades e a seguir exibe as chaves e os valores:

using System;
using System.Collections;
namespace Exemplo2
{
    class Program
    {
        static void Main(string[] args)
        {
            Hashtable hashtable = new Hashtable();
            hashtable.Add(100, "Santos");
            hashtable.Add(200, "Campinas");
            hashtable.Add(300, "Americana");
            hashtable.Add(400, "Lins");
            hashtable.Add(500, "Catanduva");
            // Exibe as chaves
            foreach (int key in hashtable.Keys)
            {
               Console.WriteLine("Chaves : " + key);
            }
            // Exibe os valores
            foreach (string value in hashtable.Values)
            {
               Console.WriteLine("Valores : "  + value);
            }
            Console.ReadKey();
        }
    }
}

3-) Neste exemplo estamos usando os métodos ContainsKey e Contains para verificar se uma chave já existe na HashTable:

using System;
using System.Collections;
namespace Exemplo3
{
    class Program
    {
        static Hashtable GetHashtable()
        {
            // Cria a retorna um novo Hashtable.
            Hashtable hashtable = new Hashtable();
            hashtable.Add("Despesas", 1000);
            hashtable.Add("Receitas", 1550);
            hashtable.Add("Alimentos", 190);
            hashtable.Add("Viagens", 440);
            hashtable.Add("Pagamentos", 27);
            return hashtable;
        }
        static void Main(string[] args)
        {
            Hashtable hashtable = GetHashtable();
            // Verifica se a Hashtable contém esta chave
            Console.WriteLine(hashtable.ContainsKey("Alimentos"));
            // Testa o método Contains p/ver funciona igual a ContainsKey
            Console.WriteLine(hashtable.Contains("Viagens"));
            // Pega o valor da Area como o indice
            int value = (int)hashtable["Viagens"];
            // Escreve o valor da área
            Console.WriteLine(value);
            Console.ReadKey();
        }
    }
}

Quando devo usar uma HashTable ?

Quando você precisar procurar itens em uma coleção pela chave.

Diferenças entre a classe HashTable e Dictionary:

HashTable

Dictionary

Retorna nulo se tentarmos encontrar uma chave que não existe.
É mais lento do que um Dictionary porque requer boxing e unboxing.
Todos os membros de um Hashtable são thread safe.
Não é um tipo genérico. O que significa que não podemos usá-lo com qualquer tipo de dados.
Retorna um erro se tentar encontrar uma chave que não existe.
É mais rápido do que um Hashtable porque não há boxing e unboxing.
Somente membros estáticos públicos são thread-safe.
É um tipo genérico, logo podemos usá-lo com qualquer tipo de dados.

Pegue o projeto completo aqui:  HashTable.zip

Não vos esqueçais da hospitalidade, porque por ela alguns, não o sabendo, hospedaram anjos.
Hebreus 13:2

Referências:


José Carlos Macoratti