O hashCode()
método da classe Boolean é implementado assim:
public int hashCode() {
return value ? 1231 : 1237;
}
Por que ele usa 1231 e 1237? Por que não outra coisa?
O hashCode()
método da classe Boolean é implementado assim:
public int hashCode() {
return value ? 1231 : 1237;
}
Por que ele usa 1231 e 1237? Por que não outra coisa?
Respostas:
1231 e 1237 são apenas dois números primos arbitrários (suficientemente grandes) . Quaisquer outros dois grandes números primos serviriam bem.
Por que primos?
Suponha por um segundo que escolhemos números compostos (não primos), digamos 1000 e 2000. Ao inserir booleanos em uma tabela hash, verdadeiro e falso iriam para o balde 1000 % N
resp 2000 % N
(onde N
é o número de baldes).
Agora observe que
1000 % 8
mesmo balde que 2000 % 8
1000 % 10
mesmo balde que 2000 % 10
1000 % 20
mesmo balde que 2000 % 20
em outras palavras, isso levaria a muitas colisões .
Isso ocorre porque a fatoração de 1000 (2 3 , 5 3 ) e a fatoração de 2000 (2 4 , 5 3 ) têm muitos fatores comuns. Assim, os números primos são escolhidos, uma vez que é improvável que tenham quaisquer fatores comuns com o tamanho do balde.
Por que grandes primos. 2 e 3 não serviriam?
Ao calcular códigos hash para objetos compostos, é comum adicionar os códigos hash para os componentes. Se valores muito pequenos forem usados em um conjunto hash com um grande número de depósitos, há o risco de acabar com uma distribuição desigual de objetos.
As colisões importam? Os booleanos simplesmente têm dois valores diferentes?
Os mapas podem conter booleanos junto com outros objetos. Além disso, como apontado por Drunix, uma maneira comum de criar funções hash de objetos compostos é reutilizar as implementações de código hash dos subcomponentes, caso em que é bom retornar grandes números primos.
Perguntas relacionadas:
2*1231 = 2462
baldes. As colisões são um problema em tal situação?