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:
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:
Uma Hashtable não pode conter chaves duplicadas;
Se você chamar o método Add para adicionar uma chave que já está presente na matriz de chaves, você terá uma exceção;
Você pode, no entanto, usar a notação entre parênteses para adicionar um par chave/valor (como mostrado no exemplo a seguir), sem perigo de obter uma exceção, mesmo que já tenha sido adicionado a chave;
Você pode testar se um Hashtable já contém uma chave específica usando o método ContainsKey;
Internamente, uma Hashtable é uma estrutura de dados esparsos que atua melhor quando tem uma abundância de memória para funcionar.;
O tamanho de uma tabela de hash na memória pode crescer muito mais rapidamente conforme você inclui mais elementos;
Quando você usa uma declaração foreach para percorrer uma Hashtable, você recebe de volta um DictionaryEntry;
A classe DictionaryEntry fornece acesso à chave e ao valor dos elementos em ambas as matrizes através das propriedades Key e Value;
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: