C# - O que é Hashcode e qual sua finalidade? -
- Início » Programação » C# – O que é Hashcode e qual sua finalidade?
2 de março de 2017 0 Por Ramos de Souza Janones
O termo hash "costuma" ser traduzido por espalhamento. Algumas pessoas podem dizer que é triturar (o dado até ficar um pedacinho), veremos como utilizar com o C#.
Uma tabela hash consegue localizar um elemento quase sempre em complexidade O(1), ou seja, não importa o tamanho da tabela, ele acha sempre no mesmo tempo. Isso é o mesmo que acontece com um array. Como ele consegue colocar dados diversos que não são números, ou pelo menos não são números simples e em sequencia e permanecer tão rápido?
Ele pega o dado real aplica uma fórmula para descobrir qual é o número que aquele dado corresponde. Esse cálculo é feito no que chamamos hash function. Uma boa função tentar evitar que dois dados diferentes gerem o mesmo resultado. Embora seja provável que não gere repetidos, acontece, especialmente em volumes grandes de dados. Quando isto ocorre, a complexidade vai para O(M), onde M é a quantidade de repetições. Como não costuma ter muita repetição, dizemos que a complexidade de uma tabela hash é quase O(1). Só não é 1 quando tem repetição. Em tese em um caso extremo o O(1) poderia virar O(N), ou seja, ter que ver tudo. Na prática isso não ocorre, a não ser que faça essa piada:
function getHashCode() { return 42; }
Aí todas chaves gerarão o mesmo resultado e só terá repetição na tabela.
LEIA TAMBÉM: Como usar Yield no Python?
React – O que é Shadow DOM?
Entendendo Waterfall e Scrum e quando usar?
O hash code pode ser só calculado na hora que precisa, ou pode ser armazenado no objeto trocando tempo de processamento por espaço ocupado.
Sem um objeto não pode ter uma forma de calcular seu hash de forma confiável, ele não pode ser usado em uma tabela de hash. Claro que todo objeto pode ser hasheável, mas se isso será bem organizado ou não, depende da linguagem e do programador.
Linguagens como Java e C# obrigam todo objeto ter uma função que calcula o hash. Se vai armazenar ou não (cache) é problema de cada objeto. Algumas pessoas dizem que isso é um erro e que deveria ter uma interface Hashable para usar em objetos que podem fazer bom uso do código. Outros dizem que já que é praticamente todo objeto que pode ser usado, então é melhor obrigador em todos.
Um objeto pode usar a implementação padrão ou fazer um próprio. Muitas vezes tem que fazer o próprio usando as partes do objeto que são relevantes para identificar o objeto.
A comparação não é tão boa, mas vamos dizer que é o RG do objeto (no Brasil, o documento de identidade da pessoa), que inclusive pode ter repetido porque os estados é que controlam isso. É verdade que a identidade completa do objeto RG seria seu número e órgão emissor, aí ficaria único.
Algumas linguagens usam isto para poder usar estruturas mais complexas em case do switch.
O case precisa ser rápido, não pode fazer comparações complexas, precisa ter um padrão fácil de localização. Ele se assemelha muito com uma tabela hash. Usando o hash code da string dá para tornar o switch mais poderoso e aceitar um tipo que é muito útil em uma seleção múltipla.
Em alguns casos o código pode ser gravado ou transmitido junto servindo de verificação da integridade do dado. Depois ele calcula de novo e vê se bate com o que foi transmitido pra ver se houve alguma corrupção. Não é uma forma muito confiável, mas pode ser usada se souber o que está fazendo e puder lidar com algum possível erro.
Outros usos podem ser feitos talvez para otimizar algum algoritmo. O código hash pode servir para identificar que algo é diferente mais rapidamente do que olhar um objeto enorme. Ele mais um trecho do objeto pode quase garantir a unicidade. Ele sozinho não é tão útil para isto. Não que isto costume ser usado na prática.
De maneira geral é usado para comparações, mas nada impede de ser usado para outras coisas. Dá pra ser criativo.
Diferenças entre integração contínua, deploy e entrega contínua?
Não confundir com outros tipo de hash code, normalmente enormes que são usados para assinar ou autenticar objetos. Esse é bem pequeno, geralmente 4 bytes.
Não vejo porque seria diferente em programação funcional, a não ser que pode haver otimizações do pattern matching como o citado sobre o switch.
O que eu posso dizer é que em programação funcional os objetos tendem a ser mais propícios para uso em tabela hash já que eles são imutáveis. Essa é uma característica importante do objeto para usar em tabela de espalhamento.