Para que é utilizado o hashCode? É único?

129

Percebo que há um getHashCode()método em todos os controles, itens, no WP7, que retornam uma sequência de número. Posso usar esse código de hash para identificar um item? Por exemplo, eu quero identificar uma imagem ou uma música no dispositivo e verificar a localização. Isso pode ser feito se o código hash fornecido para itens específicos for exclusivo.

Você pode me ajudar a explicar para que serve o hashCode getHashCode()?

Nghia Nguyen
fonte
Eu sei o que significa hashCode, tento executar meu código várias vezes para obter o código hash e ele retorna o mesmo código hash para os mesmos itens sempre e não parece ser duplicado, mas não tenho muita certeza. Bem, tudo bem se você quiser votar, é a sua opinião. Obrigado pela edição de qualquer maneira!
Nghia Nguyen
7
Eu recomendo ler as Diretrizes e regras de Eric Lippert para GetHashCode , embora ele se concentre nas regras para implementar os HashCodes em vez das regras para usá-los ... como elas são " por design útil apenas por uma coisa: colocar um objeto em uma tabela de hash"
Brian

Respostas:

108

MSDN diz :

Um código de hash é um valor numérico usado para identificar um objeto durante o teste de igualdade. Também pode servir como um índice para um objeto em uma coleção.

O método GetHashCode é adequado para uso em algoritmos de hash e estruturas de dados, como uma tabela de hash.

A implementação padrão do método GetHashCode não garante valores de retorno exclusivos para objetos diferentes. Além disso, o .NET Framework não garante a implementação padrão do método GetHashCode, e o valor retornado será o mesmo entre diferentes versões do .NET Framework. Conseqüentemente, a implementação padrão desse método não deve ser usada como um identificador de objeto exclusivo para fins de hash.

O método GetHashCode pode ser substituído por um tipo derivado. Os tipos de valor devem substituir esse método para fornecer uma função de hash apropriada para esse tipo e para fornecer uma distribuição útil em uma tabela de hash. Por exclusividade, o código de hash deve ser baseado no valor de um campo ou propriedade da instância em vez de um campo ou propriedade estática.

Objetos usados ​​como chave em um objeto Hashtable também devem substituir o método GetHashCode porque esses objetos devem gerar seu próprio código de hash. Se um objeto usado como chave não fornecer uma implementação útil de GetHashCode, você poderá especificar um provedor de código de hash quando o objeto Hashtable for construído. Antes do .NET Framework versão 2.0, o provedor de código de hash era baseado na interface System.Collections.IHashCodeProvider. A partir da versão 2.0, o provedor de código de hash é baseado na interface System.Collections.IEqualityComparer.

Basicamente, existem códigos de hash para tornar possíveis as hashtables.
É garantido que dois objetos iguais tenham códigos de hash iguais. Não
é garantido que dois objetos desiguais tenham códigos de hash desiguais (isso é chamado de colisão).

SLaks
fonte
3
A cotação do MSDN está desatualizada. O MSDN agora não é tão explícito sobre o código de hash não ser exclusivo.
user34660
248

Depois de aprender o que é, pensei em escrever uma explicação esperançosamente mais simples por analogia:

Resumo: O que é um código de hash?

  • É uma impressão digital. Podemos usar essa impressão digital para identificar pessoas de interesse.

Leia abaixo para mais detalhes:

Pense em um Hashcode como nós tentando identificar alguém de maneira exclusiva

Sou detetive, atento a um criminoso. Vamos chamá-lo de Sr. Cruel. (Ele era um assassino notório quando eu era criança - ele invadiu uma casa sequestrada e matou uma garota pobre, largou o corpo dela e ele ainda está solto - mas isso é um assunto à parte). O senhor Cruel tem certas características peculiares que posso usar para identificá-lo de forma única no meio de um mar de pessoas. Temos 25 milhões de pessoas na Austrália. Um deles é o Sr. Cruel. Como podemos encontrá-lo?

Maus modos de identificar o Sr. Cruel

Aparentemente, o Sr. Cruel tem olhos azuis. Isso não ajuda muito, porque quase metade da população da Austrália também tem olhos azuis.

Boas maneiras de identificar o Sr. Cruel

O que mais posso usar? Eu sei: vou usar uma impressão digital!

Vantagens :

  • É realmente muito difícil para duas pessoas ter a mesma impressão digital (não impossível, mas extremamente improvável).
  • A impressão digital do Sr. Cruel nunca muda.
  • Cada parte de todo o ser do Sr. Cruel: sua aparência, cor do cabelo, personalidade, hábitos alimentares etc. deve (idealmente) refletir-se em sua impressão digital, de modo que, se ele tem um irmão (que é muito parecido, mas não é o mesmo) - então ambos deve ter impressões digitais diferentes . Eu digo "deveria" porque não podemos garantir 100% que duas pessoas neste mundo terão impressões digitais diferentes.
  • Mas sempre podemos garantir que o Sr. Cruel sempre terá a mesma impressão digital - e que a impressão digital NUNCA mudará.

As características acima geralmente proporcionam boas funções de hash.

Então, qual é o problema com 'colisões'?

Imagine se eu conseguir uma pista e encontrar alguém que combine com as impressões digitais do Sr. Cruel. Isso significa que eu encontrei o Sr. Cruel?

........possivelmente! Eu devo dar uma olhada mais de perto. Se estou usando o SHA256 (uma função de hash) e estou procurando em uma cidade pequena com apenas 5 pessoas - há uma chance muito boa de encontrá-lo! Mas se eu estiver usando o MD5 (outra famosa função de hash) e verificando impressões digitais em uma cidade com + 2 ^ 1000 pessoas, é uma possibilidade bastante boa que duas pessoas completamente diferentes tenham a mesma impressão digital.

Então, qual é o benefício de tudo isso?

O único benefício real dos códigos de hash é se você deseja colocar algo em uma tabela de hash - e com tabelas de hash você deseja encontrar objetos rapidamente - e é aí que o código de hash entra. Eles permitem que você encontre coisas realmente em tabelas de hash rapidamente. É um truque que melhora enormemente o desempenho, mas com uma pequena despesa de precisão.

Então, vamos imaginar que temos uma tabela de hash cheia de pessoas - 25 milhões de suspeitos na Austrália. Sr. Cruel está em algum lugar lá ... Como podemos encontrá-lo muito rapidamente ? Precisamos resolver todos eles: encontrar uma possível correspondência ou absolver potenciais suspeitos. Você não quer considerar as características únicas de cada pessoa, porque isso levaria muito tempo. O que você usaria em vez disso? Você usaria um código hash! Um código hash pode dizer se duas pessoas são diferentes. Se Joe Bloggs NÃO é o Sr. Cruel. Se as impressões não combinarem, você sabe que definitivamente NÃO é o Sr. Cruel. Mas, se as impressões digitais corresponderementão, dependendo da função de hash usada, as chances já são razoavelmente boas de você encontrar o seu homem. Mas não é 100%. A única maneira de ter certeza é investigar mais: (i) ele / ela teve uma oportunidade / motivo, (ii) testemunhas etc.

Quando você estiver usando computadores se dois objetos tiverem o mesmo valor de código de hash, será necessário investigar novamente se eles são realmente iguais. por exemplo, você teria que verificar se os objetos têm, por exemplo, a mesma altura, o mesmo peso, etc., se os números inteiros são iguais ou se o customer_id é uma correspondência e, em seguida, chegar à conclusão de que são iguais. isso geralmente é feito talvez implementando uma interface IComparer ou IEquality.

Resumo das Chaves

Então, basicamente, um código hash é uma impressão digital.

Impressão digital digital - Atributo de imagem à Pixabay - Disponível gratuitamente para uso em: https://pixabay.com/en/finger-fingerprint-security-digital-2081169/

  1. Duas pessoas / objetos diferentes podem teoricamente ainda ter a mesma impressão digital. Ou em outras palavras. Se você tem duas impressões digitais iguais ......... elas não precisam ser da mesma pessoa / objeto.
  2. Além disso, a mesma pessoa / objeto sempre retornará a mesma impressão digital .
  3. O que significa que, se dois objetos retornarem códigos de hash diferentes , você terá 100% de certeza de que esses objetos são diferentes.

Demora uns bons 3 minutos para entender o que precede. Talvez leia algumas vezes até que faça sentido. Espero que isso ajude alguém, porque foi preciso muito sofrimento para aprender tudo!

BKSpurgeon
fonte
1
Re: A documentação do MSDN matou algumas células do meu cérebro .... levou algumas das minhas à beira do suicídio. só salvou porque eu adormeci;)
Shwrk
Você destruiu toda a sua bela explicação com esse comentário asterisco no final.
Waldemar Gałęzinowski
Eu amei! principalmente o nome "Mr.Cruel!"
João Pedro Andrade Marques
Como um verdadeiro fã de crime, esta é provavelmente a minha resposta SO mais favorita ... de todos os tempos.
IfElseTryCatch
11

GetHashCode()é usado para ajudar no suporte ao uso do objeto como uma chave para tabelas de hash. (Uma coisa semelhante existe em Java etc). O objetivo é que cada objeto retorne um código de hash distinto, mas isso geralmente não pode ser absolutamente garantido. É necessário, no entanto, que dois objetos logicamente iguais retornem o mesmo código de hash.

Uma implementação típica de tabela de hash começa com o valor hashCode, pega um módulo (restringindo assim o valor dentro de um intervalo) e o usa como um índice para uma matriz de "buckets".

seand
fonte
8

Não é exclusivo do WP7 - está presente em todos os objetos .Net. Faz o que você descreve, mas eu não o recomendaria como um identificador exclusivo nos seus aplicativos, pois não é garantido que ele seja único.

Método Object.GetHashCode

Phil Sandler
fonte
4

Isto é do artigo do msdn aqui:

https://blogs.msdn.microsoft.com/tomarcher/2006/05/10/are-hash-codes-unique/

"Enquanto você ouvirá as pessoas afirmarem que os códigos de hash geram um valor único para uma determinada entrada, o fato é que, embora difícil de realizar, é tecnicamente possível encontrar duas entradas de dados diferentes que tenham o mesmo valor . No entanto, a verdadeira os fatores determinantes relacionados à eficácia de um algoritmo de hash estão no comprimento do código de hash gerado e na complexidade dos dados que estão sendo hash ".

Portanto, basta usar um algoritmo de hash adequado ao tamanho dos seus dados e ele terá códigos de hash exclusivos.

Shree Harsha
fonte