Recentemente, li este documento do Developer Works .
O documento é tudo sobre a definição hashCode()
e equals()
de forma eficaz e correcta, no entanto eu não sou capaz de descobrir por que precisamos substituir esses dois métodos.
Como posso tomar a decisão de implementar esses métodos com eficiência?
Respostas:
Joshua Bloch diz sobre Java eficaz
Vamos tentar entender isso com um exemplo do que aconteceria se substituíssemos
equals()
sem substituirhashCode()
e tentássemos usar aMap
.Digamos que temos uma classe como esta e que dois objetos de
MyClass
são iguais se os seusimportantField
forem iguais (comhashCode()
eequals()
gerados pelo eclipse)Substituir apenas
equals
Se apenas
equals
for anulado, quando você chamarmyMap.put(first,someValue)
primeiro o hash de um balde e quando você o chamarmyMap.put(second,someOtherValue)
, o hash de outro balde (como eles têm um diferentehashCode
). Portanto, embora sejam iguais, pois não fazem o hash no mesmo intervalo, o mapa não consegue perceber e os dois permanecem no mapa.Embora não seja necessário substituir,
equals()
se substituirmoshashCode()
, vamos ver o que aconteceria nesse caso específico, onde sabemos que dois objetos deMyClass
são iguais se osimportantField
mesmos forem iguais, mas não substituímosequals()
.Substituir apenas
hashCode
Imagine que você tem isso
Se você substituir apenas
hashCode
, quando ligarmyMap.put(first,someValue)
primeiro, calculahashCode
e armazena em um determinado intervalo. Então, quando você ligarmyMap.put(second,someOtherValue)
, substitua primeiro pelo segundo, conforme a Documentação do Mapa, pois eles são iguais (de acordo com os requisitos de negócios).Mas o problema é que iguais não foram redefinidos; portanto, quando o mapa
second
passa e percorre o balde, procurando se existe algum objetok
quesecond.equals(k)
seja verdadeiro, ele não encontrará o quesecond.equals(first)
seráfalse
.Espero que esteja claro
fonte
if you think you need to override one, then you need to override both of them
está errado. Você precisa substituirhashCode
se a sua classe substitui,equals
mas a reversão não é verdadeira.equals
violaria o contrato descrito no javadoc deObject
: "Se dois objetos forem iguais de acordo com oequals(Object)
método, a chamada dohashCode
método em cada um dos dois objetos deverá produzir o mesmo resultado inteiro". Claro, nem todas as partes de todos os contratos são exercidas em todo o código, mas ainda assim, formalmente, é uma violação e eu consideraria um bug esperando para acontecer.Coleções como
HashMap
eHashSet
usam um valor de código de hash de um objeto para determinar como ele deve ser armazenado dentro de uma coleção, e o código de hash é usado novamente para localizar o objeto em sua coleção.A recuperação de hash é um processo de duas etapas:
hashCode()
)equals()
)Aqui está um pequeno exemplo de por que devemos substituir
equals()
ehashcode()
.Considere uma
Employee
classe que possui dois campos: idade e nome.Agora crie uma classe, insira o
Employee
objeto em umHashSet
e teste se esse objeto está presente ou não.Ele imprimirá o seguinte:
Agora, remova o comentário do
hashcode()
método, execute o mesmo e a saída seria:Agora você pode ver por que, se dois objetos são considerados iguais, seus códigos de hash também devem ser iguais? Caso contrário, você nunca seria capaz de encontrar o objeto, já que o método padrão de código de hash na classe Object praticamente sempre apresenta um número exclusivo para cada objeto, mesmo que o
equals()
método seja substituído de tal maneira que dois ou mais objetos sejam considerados iguais . Não importa quão iguais sejam os objetos, se seus códigos de hash não refletirem isso. Então, mais uma vez: se dois objetos são iguais, seus hashcode s também devem ser iguais.fonte
Ao definir
equals()
ehashCode()
consistentemente, você pode melhorar a usabilidade de suas classes como chaves em coleções baseadas em hash. Como o documento da API do hashCode explica: "Este método é suportado para o benefício de tabelas de hash, como as fornecidas porjava.util.Hashtable
".A melhor resposta para sua pergunta sobre como implementar esses métodos com eficiência está sugerindo que você leia o Capítulo 3 de Java Efetivo .
fonte
hashCode()
.Simplificando, o método equals em Object verifica a igualdade de referência, onde duas instâncias da sua classe ainda podem ser semanticamente iguais quando as propriedades são iguais. Isso é importante, por exemplo, ao colocar seus objetos em um contêiner que utilize iguais e hashcode, como HashMap e Set . Digamos que temos uma classe como:
Criamos duas instâncias com o mesmo ID :
Sem substituir os iguais, estamos obtendo:
Corrigir? Bem, talvez, se é isso que você quer. Mas digamos que queremos que objetos com o mesmo ID sejam o mesmo objeto, independentemente de serem duas instâncias diferentes. Substituímos os iguais (e código de hash):
Quanto à implementação de equals e hashcode, posso recomendar o uso dos métodos auxiliares do Guava
fonte
Identidade não é igualdade.
==
identidade do teste do operador .equals(Object obj)
O método compara o teste de igualdade (ou seja, precisamos dizer à igualdade substituindo o método)Primeiro, precisamos entender o uso do método equals.
Para identificar diferenças entre dois objetos, precisamos substituir o método equals.
Por exemplo:
Agora, o método hashCode pode entender facilmente.
hashCode produz um número inteiro para armazenar objetos em estruturas de dados como HashMap , HashSet .
Suponha que substituímos o método igual a
Customer
acima,Enquanto trabalhamos com a estrutura de dados quando armazenamos objetos em buckets (bucket é um nome sofisticado para pasta). Se usarmos a técnica de hash integrada, para mais de dois clientes, ele gera dois hashcode diferentes. Então, estamos armazenando o mesmo objeto idêntico em dois lugares diferentes. Para evitar esse tipo de problema, devemos substituir o método hashCode também com base nos seguintes princípios.
fonte
Ok, deixe-me explicar o conceito em palavras muito simples.
Primeiramente, de uma perspectiva mais ampla, temos coleções, e o hashmap é uma das estruturas de dados nas coleções.
Para entender por que precisamos substituir o método equals e hashcode, se for necessário primeiro entender o que é o hashmap e o que ele faz.
Um hashmap é uma estrutura de dados que armazena pares de dados-chave de valor de maneira array. Vamos dizer a [], onde cada elemento em 'a' é um par de valores-chave.
Além disso, cada índice na matriz acima pode ser vinculado à lista, tendo assim mais de um valor em um índice.
Agora, por que um hashmap é usado? Se tivermos que pesquisar em uma matriz grande, pesquisando em cada uma delas, se elas não forem eficientes, o que a técnica de hash nos diz que permite pré-processar a matriz com alguma lógica e agrupar os elementos com base nessa lógica, por exemplo, Hashing
por exemplo: temos matriz 1,2,3,4,5,6,7,8,9,10,11 e aplicamos uma função hash mod 10 para que 1,11 sejam agrupados. Portanto, se tivéssemos que procurar 11 na matriz anterior, teríamos que iterar a matriz completa, mas quando a agrupamos, limitamos nosso escopo de iteração, melhorando assim a velocidade. Essa estrutura de dados usada para armazenar todas as informações acima pode ser vista como uma matriz 2D para simplificar
Agora, além do hashmap acima, também informa que ele não adicionará duplicados. E esta é a principal razão pela qual temos que substituir os iguais e o código de hash
Então, quando se diz que explica o trabalho interno do hashmap, precisamos descobrir quais métodos o hashmap possui e como ele segue as regras acima, que expliquei acima
portanto, o hashmap tem o método chamado como put (K, V) e, de acordo com o hashmap, ele deve seguir as regras acima para distribuir eficientemente a matriz e não adicionar duplicatas
Então, o que faz é que ele primeiro gere o código hash da chave especificada para decidir em qual índice o valor deve entrar. se nada estiver presente nesse índice, o novo valor será adicionado por lá, se algo já estiver lá o novo valor deve ser adicionado após o final da lista vinculada nesse índice. mas lembre-se de que nenhuma duplicata deve ser adicionada conforme o comportamento desejado do hashmap. então digamos que você tenha dois objetos Inteiros aa = 11, bb = 11. Como todo objeto derivado da classe de objeto, a implementação padrão para comparar dois objetos é que ele compara a referência e não os valores dentro do objeto. Portanto, no caso acima, ambos semânticos iguais serão reprovados no teste de igualdade e a possibilidade de existirem dois objetos com o mesmo código de hash e os mesmos valores, criando duplicatas. Se substituirmos, poderemos evitar adicionar duplicatas. Você também pode consultarDetalhe de trabalho
fonte
hashCode()
:Se você substituir apenas o método de código hash, nada acontecerá. Porque ele sempre retorna novo
hashCode
para cada objeto como uma classe Object.equals()
:Se você substituir apenas o método igual,
a.equals(b)
é verdade, isso significa que ohashCode
de aeb deve ser o mesmo, mas não acontecer. Porque você não substituiu ohashCode
método.Nota: o
hashCode()
método da classe Object sempre retorna novohashCode
para cada objeto.Portanto, quando você precisar usar seu objeto na coleção baseada em hash, deverá substituir ambos
equals()
ehashCode()
.fonte
Java coloca uma regra que
Portanto, se em nossa classe substituirmos
equals()
, devemos substituirhashcode()
também o método para seguir esta regra. Ambos os métodos,equals()
ehashcode()
, são usadosHashtable
, por exemplo, para armazenar valores como pares de valores-chave. Se substituirmos um e não o outro, existe a possibilidade de que eleHashtable
não funcione como queremos, se usarmos esse objeto como chave.fonte
Porque se você não os substituir, você usará a implentação padrão em Object.
Dado que os valores de igualdade e hascode da instância geralmente requerem conhecimento do que compõe um objeto, eles geralmente precisam ser redefinidos em sua classe para ter algum significado tangível.
fonte
Para usar nossos próprios objetos de classe como chaves em coleções como HashMap, Hashtable etc., devemos substituir os dois métodos (hashCode () e equals ()), tendo em mente o trabalho interno da coleção. Caso contrário, leva a resultados errados que não são esperados.
fonte
Adicionando à resposta de @Lombo
Quando você precisará substituir igual a ()?
A implementação padrão de equals () do objeto é
o que significa que dois objetos serão considerados iguais apenas se tiverem o mesmo endereço de memória, o que será verdadeiro somente se você estiver comparando um objeto com ele.
Mas você pode considerar dois objetos iguais, se eles tiverem o mesmo valor para uma ou mais de suas propriedades (consulte o exemplo dado na resposta de @Lombo).
Então você substituirá
equals()
essas situações e daria suas próprias condições para a igualdade.Eu implementei com sucesso equals () e está funcionando muito bem. Então, por que eles estão pedindo para substituir o hashCode () também?
Bem. Desde que você não use Coleções baseadas em "Hash" em sua classe definida pelo usuário, tudo bem. Mas em algum momento no futuro você poderá usar
HashMap
ou,HashSet
se não o fizeroverride
e "implementar corretamente" o hashCode () , essa coleção baseada em Hash não funcionará conforme o esperado.Substituir apenas iguais (adição à resposta de @Lombo)
Primeiro, o HashMap verifica se o hashCode de
second
é o mesmo quefirst
. Somente se os valores forem iguais, continuará a verificação da igualdade no mesmo bucket.Mas aqui o hashCode é diferente para esses 2 objetos (porque eles têm diferentes endereços de memória - da implementação padrão). Por isso, nem se importará em verificar a igualdade.
Se você tiver um ponto de interrupção dentro do método equals () substituído, ele não entrará em ação se eles tiverem hashCodes diferentes.
contains()
verificaçõeshashCode()
e somente se forem iguais, chamaria seuequals()
método.Por que não podemos fazer com que o HashMap verifique a igualdade em todos os buckets? Portanto, não há necessidade de substituir hashCode () !!
Está faltando o ponto das coleções baseadas em Hash. Considere o seguinte :
A seguir estão as chaves armazenadas na forma de baldes.
Digamos que você queira saber se o mapa contém a chave 10. Deseja pesquisar todos os baldes? ou Deseja pesquisar apenas um balde?
Com base no hashCode, você identificaria que, se 10 estiver presente, ele deverá estar presente no balde 1. Portanto, somente o balde 1 será pesquisado !!
fonte
hashCode()
para determinar o bucket e usa oequals()
método para descobrir se o valor já está presente no bucket . Caso contrário, será adicionado, caso contrário, será substituído pelo valor atualhashCode()
para encontrar a entrada (bloco) primeiro eequals()
para encontrar o valor em Entryse Ambos são substituídos,
Mapa < Um >
se igual não for substituído
Mapa < Um >
Se hashCode não for substituído
Mapa < Um >
Contrato igual de HashCode
fonte
Considere a coleção de bolas em um balde, todas na cor preta. Seu trabalho é colorir essas bolas da seguinte maneira e usá-las no jogo apropriado,
Para Tênis - Amarelo, Vermelho. Para Críquete - Branco
Agora o balde tem bolas em três cores amarelo, vermelho e branco. E que agora você fez a coloração. Só você sabe qual cor é para qual jogo.
Colorir as bolas - Hashing. Escolhendo a bola para o jogo - Igual a.
Se você fez a coloração e alguém escolhe a bola para críquete ou tênis, eles não se importam com a cor !!!
fonte
Eu estava olhando para a explicação "Se você substituir apenas o hashCode, quando o chamar
myMap.put(first,someValue)
primeiro, calcula o hashCode e o armazena em um determinado intervalo. Então, quando você o chamamyMap.put(first,someOtherValue)
, deve substituir primeiro pelo segundo, conforme a Documentação do Mapa, porque são iguais (de acordo com nossa definição). " :Acho segunda vez quando estamos adicionando,
myMap
então deve ser o 'segundo' objeto comomyMap.put(second,someOtherValue)
fonte
1) O erro comum é mostrado no exemplo abaixo.
o carro verde não foi encontrado
2. Problema causado por hashCode ()
O problema é causado pelo método não substituído
hashCode()
. O contrato entreequals()
ehashCode()
é:Se dois objetos tiverem o mesmo código de hash, eles podem ou não ser iguais.
fonte
É útil ao usar objetos de valor . A seguir, um trecho do Repositório de Padrões de Portland :
fonte
Suponha que você tenha a classe (A) que agrega duas outras (B) (C) e que você precisa armazenar instâncias de (A) dentro da hashtable. A implementação padrão apenas permite distinguir instâncias, mas não por (B) e (C). Portanto, duas instâncias de A podem ser iguais, mas o padrão não permite compará-las da maneira correta.
fonte
Os métodos equals e hashcode são definidos na classe de objeto. Por padrão, se o método equals retornar true, o sistema irá além e verificará o valor do código hash. Se o código de hash dos 2 objetos também for o mesmo, os objetos serão considerados iguais. Portanto, se você substituir apenas o método igual a, então mesmo que o método igual substituído indique que 2 objetos são iguais, o código de hash definido pelo sistema pode não indicar que os 2 objetos são iguais. Portanto, precisamos substituir o código de hash também.
fonte
true
paraequals
não ser considerado como correspondente. Por outro lado, se as coleções acontecerem, observe que as coisas não podem ter o mesmo código de hash, é provável que elas não notem que são iguais.Métodos iguais e Hashcode em Java
Eles são métodos da classe java.lang.Object, que é a superclasse de todas as classes (classes personalizadas também e outras definidas na API java).
Implementação:
públicos booleanos iguais (Object obj)
Este método simplesmente verifica se dois objetos referenciam x e y se referem ao mesmo objeto. ou seja, verifica se x == y.
É reflexivo: para qualquer valor de referência x, x.equals (x) deve retornar true.
É simétrico: para qualquer valor de referência xey, x.equals (y) deve retornar true se e somente se y.equals (x) retornar true.
É transitivo: para quaisquer valores de referência x, ye z, se x.equals (y) retornar true e y.equals (z) retornar true, x.equals (z) deverá retornar true.
É consistente: para quaisquer valores de referência xey, várias invocações de x.equals (y) retornam consistentemente true ou retornam false consistentemente, desde que nenhuma informação usada em comparações iguais no objeto seja modificada.
public int hashCode ()
Este método retorna o valor do código de hash para o objeto no qual esse método é chamado. Este método retorna o valor do código de hash como um número inteiro e é suportado para o benefício de classes de coleção baseadas em hash, como Hashtable, HashMap, HashSet etc. Este método deve ser substituído em todas as classes que substituem o método equals.
O contrato geral do hashCode é:
Sempre que é invocado no mesmo objeto mais de uma vez durante a execução de um aplicativo Java, o método hashCode deve retornar consistentemente o mesmo número inteiro, desde que nenhuma informação usada em comparações iguais no objeto seja modificada.
Esse número inteiro não precisa permanecer consistente de uma execução de um aplicativo para outra execução do mesmo aplicativo.
Se dois objetos forem iguais de acordo com o método equals (Object), a chamada do método hashCode em cada um dos dois objetos deverá produzir o mesmo resultado inteiro.
Não é necessário que, se dois objetos forem desiguais, de acordo com o método equals (java.lang.Object), a chamada do método hashCode em cada um dos dois objetos produza resultados inteiros distintos. No entanto, o programador deve estar ciente de que a produção de resultados inteiros distintos para objetos desiguais pode melhorar o desempenho das hashtables.
Recursos:
JavaRanch
Cenário
fonte
No exemplo abaixo, se você comentar a substituição de iguais ou código de hash na classe Person, esse código falhará ao procurar a ordem de Tom. O uso da implementação padrão do hashcode pode causar falhas nas pesquisas de hashtable.
O que tenho abaixo é um código simplificado que puxa a ordem das pessoas por Pessoa. A pessoa está sendo usada como uma chave na hashtable.
fonte
A classe String e as classes wrapper têm implementação
equals()
ehashCode()
métodos diferentes da classe Object. O método equals () da classe Object compara as referências dos objetos, não o conteúdo. O método hashCode () da classe Object retorna um código de hash distinto para cada objeto, independentemente de o conteúdo ser o mesmo.Isso gera problemas ao usar a coleção de mapas e a chave é do tipo Persistente, StringBuffer / tipo de construtor. Como eles não substituem equals () e hashCode (), diferentemente da classe String, equals () retornará false quando você comparar dois objetos diferentes, embora ambos tenham o mesmo conteúdo. Isso fará com que o hashMap armazene as mesmas chaves de conteúdo. Armazenar as mesmas chaves de conteúdo significa que ele está violando a regra do Mapa, porque o Mapa não permite chaves duplicadas. Portanto, você substitui os métodos equals () e hashCode () em sua classe e fornece a implementação (o IDE pode gerar esses métodos) para que funcionem da mesma forma que os equals () e hashCode () da String e evitam as mesmas chaves de conteúdo.
Você deve substituir o método hashCode () junto com equals () porque equals () funciona de acordo com o código hash.
Além disso, a substituição do método hashCode () junto com equals () ajuda a intactar o contrato equals () - hashCode (): "Se dois objetos são iguais, eles devem ter o mesmo código de hash."
Quando você precisa escrever uma implementação personalizada para hashCode ()?
Como sabemos, o trabalho interno do HashMap é baseado no princípio do Hashing. Existem certos depósitos nos quais os conjuntos de entradas são armazenados. Você personaliza a implementação hashCode () de acordo com seus requisitos para que os mesmos objetos de categoria possam ser armazenados no mesmo índice. Quando você armazena os valores na coleção de mapas usando o
put(k,v)
método, a implementação interna de put () é:Significa que ele gera índice e o índice é gerado com base no código de hash de um objeto-chave específico. Portanto, faça com que esse método gere código de hash de acordo com seus requisitos, porque os mesmos conjuntos de entradas de código de hash serão armazenados no mesmo intervalo ou índice.
É isso aí!
fonte
hashCode()
O método é usado para obter um número inteiro exclusivo para um determinado objeto. Esse número inteiro é usado para determinar a localização do depósito, quando esse objeto precisa ser armazenado em algunsHashTable
,HashMap
como na estrutura de dados. Por padrão, ohashCode()
método do objeto retorna e representação inteira do endereço da memória em que o objeto está armazenado.O
hashCode()
método dos objetos é usado quando os inserimos em umHashTable
,HashMap
ouHashSet
. Mais sobreHashTables
a Wikipedia.org para referência.Para inserir qualquer entrada na estrutura de dados do mapa, precisamos de chave e valor. Se a chave e os valores forem tipos de dados definidos pelo usuário,
hashCode()
a chave determinará onde armazenar o objeto internamente. Quando também é necessário procurar o objeto no mapa, o código de hash da chave determinará onde procurar o objeto.O código de hash aponta apenas para uma determinada "área" (ou lista, bloco, etc) internamente. Como objetos de chave diferentes podem potencialmente ter o mesmo código de hash, o próprio código de hash não garante que a chave correta seja encontrada. Em
HashTable
seguida, itera essa área (todas as chaves com o mesmo código de hash) e usa oequals()
método da chave para encontrar a chave correta. Depois que a chave correta é encontrada, o objeto armazenado para essa chave é retornado.Portanto, como podemos ver, uma combinação dos métodos
hashCode()
eequals()
é usada ao armazenar e procurar objetos em umHashTable
.NOTAS:
Sempre use os mesmos atributos de um objeto para gerar
hashCode()
eequals()
ambos. Como no nosso caso, usamos a identificação do funcionário.equals()
deve ser consistente (se os objetos não forem modificados, ele deverá continuar retornando o mesmo valor).Sempre
a.equals(b)
, entãoa.hashCode()
deve ser o mesmo queb.hashCode()
.Se você substituir um, deverá substituir o outro.
http://parameshk.blogspot.in/2014/10/examples-of-comparable-comporator.html
fonte
hashCode()
não é usado para retornar um número inteiro exclusivo para cada objeto. Isso é impossível. Você mesmo contradiz isso na segunda frase do quarto parágrafo.IMHO, é como diz a regra - Se dois objetos são iguais, então eles devem ter o mesmo hash, ou seja, objetos iguais devem produzir valores de hash iguais.
Dado acima, o padrão equals () em Object é ==, que faz comparação no endereço, hashCode () retorna o endereço em número inteiro (hash no endereço real), que é novamente distinto para Objeto distinto.
Se você precisar usar os objetos personalizados nas coleções baseadas em Hash, precisará substituir equals () e hashCode (), por exemplo, se eu quiser manter o HashSet dos objetos Employee, se eu não usar hashCode mais forte e igual a Posso acabar substituindo os dois objetos de funcionário diferentes, isso acontece quando uso a idade como o hashCode (), mas devo usar o valor exclusivo que pode ser o ID do funcionário.
fonte
Para ajudá-lo a verificar objetos duplicados, precisamos de um igual personalizado e hashCode.
Como o código hash sempre retorna um número, é sempre rápido recuperar um objeto usando um número em vez de uma chave alfabética. Como vai fazer? Suponha que criamos um novo objeto passando algum valor que já está disponível em outro objeto. Agora, o novo objeto retornará o mesmo valor de hash de outro objeto, porque o valor passado é o mesmo. Depois que o mesmo valor de hash é retornado, a JVM sempre acessa o mesmo endereço de memória e, se houver mais de um objeto presente para o mesmo valor de hash, ele usará o método equals () para identificar o objeto correto.
fonte
Quando você deseja armazenar e recuperar seu objeto personalizado como uma chave no Mapa, sempre substitua igual e hashCode no seu Objeto personalizado. Por exemplo:
Aqui, p1 e p2 considerarão apenas um objeto e o
map
tamanho será apenas 1, porque são iguais.fonte
Classe de teste
Em Object Class igual (Object obj) é usado para comparar a comparação de endereços; por isso, quando na classe Test, se você comparar dois objetos, então é igual a método false, mas quando substituímos o código hash (), ele pode comparar o conteúdo e fornecer o resultado adequado.
fonte
Se você substituir
equals()
e nãohashcode()
, não encontrará nenhum problema, a menos que você ou outra pessoa use esse tipo de classe em uma coleção de hash comoHashSet
. As pessoas antes de mim explicaram claramente a teoria documentada várias vezes; estou aqui apenas para fornecer um exemplo muito simples.Considere uma classe cuja
equals()
necessidade de significar algo personalizado:Agora considere esta classe principal: -
Isso produzirá a seguinte saída: -
Eu estou feliz com os resultados. Mas se eu não tiver substituído
hashCode()
, ele causará pesadelo, pois objetosRishav
com o mesmo conteúdo de membro não serão mais tratados como únicos, poishashCode
serão diferentes, conforme gerado pelo comportamento padrão, eis a saída:fonte
Ambos os métodos são definidos na classe Object. E ambos estão em sua implementação mais simples. Portanto, quando você precisar, adicione mais implementação a esses métodos, substituindo sua classe.
Para o método Ex: equals () no objeto, apenas verifica sua igualdade na referência. Portanto, se você precisar comparar seu estado também, poderá substituí-lo, como é feito na classe String.
fonte
Bah - "Você deve substituir hashCode () em todas as classes que substituem igual a ()."
[do Effective Java, de Joshua Bloch?]
Não é esse o caminho errado? A substituição do hashCode provavelmente implica que você está escrevendo uma classe de chave de hash, mas a substituição de igual certamente não. Existem muitas classes que não são usadas como chaves de hash, mas desejam um método de teste de igualdade lógica por algum outro motivo. Se você escolher "iguais" para ele, poderá ser solicitado a escrever uma implementação de hashCode pela aplicação excessiva de zelo desta regra. Tudo o que consegue é adicionar código não testado na base de código, um mal esperando para enganar alguém no futuro. Também escrever código que você não precisa é anti-ágil. Está errado (e um ide gerado provavelmente será incompatível com seus iguais criados à mão).
Certamente eles deveriam ter exigido uma interface em objetos escritos para serem usados como chaves? Independentemente disso, o Object nunca deveria ter fornecido o padrão hashCode () e igual a () imho. Provavelmente, incentivou muitas coleções de hash quebradas.
De qualquer forma, acho que a "regra" está escrita de trás para frente. Enquanto isso, continuarei evitando usar "iguais" para os métodos de teste de igualdade :-(
fonte