Primeiramente, antes de definirmos o hashcode Java, precisamos entender o que é hashing e para que serve. Hashing é um processo de aplicação de uma função de hash a alguns dados. Uma função hash é apenas uma função matemática. Não se preocupe com isso! “Matemático” nem sempre significa “complicado”. Aqui significa apenas que temos alguns dados e uma certa regra que mapeia os dados em um conjunto de caracteres (código). Por exemplo, pode ser uma cifra hexadecimal. Temos alguns dados de qualquer tamanho na entrada e aplicamos uma função hash a eles. Na saída, obtemos dados de tamanho fixo, digamos, 32 caracteres. Normalmente, esse tipo de função converte um grande pedaço de dados em um pequeno valor inteiro. O resultado desse trabalho de função é chamado de código hash. As funções de hash são amplamente usadas em criptografia e em algumas outras áreas também. As funções hash podem ser diferentes,
Um determinado objeto tem um determinado hashcode.
Se dois objetos são iguais, seus hashcodes são os mesmos. O contrário não é verdade.
Se os códigos hash forem diferentes, os objetos não são iguais com certeza.
Objetos diferentes podem ter o mesmo código hash. No entanto, é um evento muito improvável. Nesse ponto, temos uma colisão, uma situação em que podemos perder dados.
A função hash "adequada" minimiza a probabilidade de colisões.
Código Hash em Java
Em Java, a função hash geralmente é conectada ao método hashCode() . Precisamente, o resultado da aplicação de uma função hash a um objeto é um código hash. Todo objeto Java possui um código hash. Em geral, o Código Hash é um número calculado pelo método hashCode() da Objectclasse. Normalmente, os programadores substituem esse método para seus objetos, bem como relacionados a hashCode() o método equals() para processamento mais eficiente de dados específicos. O método hashCode() retorna um valor int (4 bytes), que é uma representação numérica do objeto. Esse hashcode é usado, por exemplo, por coleções para armazenamento mais eficiente de dados e, consequentemente, acesso mais rápido a eles. Por padrão, o hashCode()função para um objeto retorna o número da célula de memória onde o objeto está armazenado. Portanto, se nenhuma alteração for feita no código do aplicativo, a função deverá retornar o mesmo valor. Se o código mudar ligeiramente, o valor hashcode também mudará. Para que serve o hashcode em Java? Em primeiro lugar, os hashcodes Java ajudam os programas a serem executados mais rapidamente. Por exemplo, se compararmos dois objetos o1e o2de algum tipo, a operação o1.equals(o2)leva cerca de 20 vezes mais tempo do que o1.hashCode() == o2.hashCode().
Java é igual a()
Na classe pai Object, junto com o método hashCode() , também existe equals() , a função que é usada para verificar a igualdade de dois objetos. A implementação padrão dessa função simplesmente verifica os links de dois objetos quanto à sua equivalência. equals() e hashCode() têm seu contrato, portanto, se você substituir um deles, deverá substituir o outro, para não quebrar este contrato.
Implementando o método hashCode()
Exemplo
Vamos criar uma classe Character com um campo — name . Depois disso, criamos dois objetos da classe Character , character1 e character2 e os definimos com o mesmo nome. Se usarmos o padrão hashCode() e equals() da classe Object , definitivamente obteremos objetos diferentes, não iguais. É assim que funciona o hashcode em Java. Eles terão hashcodes diferentes porque estão em células de memória diferentes e o resultado da operação equals() será falso.
import java.util.Objects;
public class Character {
private String Name;
public Character(String name) {
Name = name;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public static void main(String[] args) {
Character character1 = new Character("Arnold");
System.out.println(character1.getName());
System.out.println(character1.hashCode());
Character character2 = new Character("Arnold");
System.out.println(character2.getName());
System.out.println(character2.hashCode());
System.out.println(character2.equals(character1));
}
}
O resultado da execução do programa:
Arnold
1595428806
Arnold
1072408673
false
Dois números de 10 dígitos no console são códigos hash. E se quisermos ter objetos iguais se eles tiverem os mesmos nomes? O que deveríamos fazer? A resposta: devemos sobrescrever os métodos hashCode() e equals() da classe Object para nossa classe Character . Poderíamos fazer isso automaticamente no IDEA IDE, basta pressionar alt + insert no teclado e escolher Generate -> equals() e hashCode() . No caso do nosso exemplo temos o seguinte código:
import java.util.Objects;
public class Character {
private String Name;
public Character(String name) {
Name = name;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Character)) return false;
Character character = (Character) o;
return getName() != null ? getName().equals(character.getName()) : character.getName() == null;
}
@Override
public int hashCode() {
return getName() != null ? getName().hashCode() : 0;
}
public static void main(String[] args) {
Character character1 = new Character("Arnold");
System.out.println(character1.getName());
System.out.println(character1.hashCode());
Character character2 = new Character("Arnold");
System.out.println(character2.getName());
System.out.println(character2.hashCode());
System.out.println(character2.equals(character1));
}
}
O resultado da execução deste código:
Arnold
1969563338
Arnold
1969563338
true
Então agora o programa identifica nossos objetos como iguais e eles têm os mesmos hashcodes.
Exemplo de hashcode Java:
Seu próprio hashCode() e equals()
Você também pode criar suas próprias realizações equals() e hashCode() , mas tenha cuidado e lembre-se de minimizar as colisões de hashcode. Aqui está um exemplo de nossos próprios métodos hashCode() e equals() na classe Aluno :
import java.util.Date;
public class Student {
String surname;
String name;
String secondName;
Long birthday; // Long instead of long is used by Gson/Jackson json parsers and various orm databases
public Student(String surname, String name, String secondName, Date birthday ){
this.surname = surname;
this.name = name;
this.secondName = secondName;
this.birthday = birthday == null ? 0 : birthday.getTime();
}
//Java hashcode example
@Override
public int hashCode(){
//TODO: check for nulls
//return surname.hashCode() ^ name.hashCode() ^ secondName.hashCode() ^ (birthday.hashCode());
return (surname + name + secondName + birthday).hashCode();
}
@Override
public boolean equals(Object other_) {
Student other = (Student)other_;
return (surname == null || surname.equals(other.surname) )
&& (name == null || name.equals(other.name))
&& (secondName == null || secondName.equals(other.secondName))
&& (birthday == null || birthday.equals(other.birthday));
}
}
E a classe Main para demonstrar seu trabalho:
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
public class Main {
static HashMap<Student, Integer> cache = new HashMap<Student, Integer>(); // <person, targetPriority>
public static void main(String[] args) {
Student sarah1 = new Student("Sarah","Connor", "Jane", null);
Student sarah2 = new Student("Sarah","Connor", "Jane", new Date(1970, 01-1, 01));
Student sarah3 = new Student("Sarah","Connor", "Jane", new Date(1959, 02-1, 28)); // date not exists
Student john = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28)); // date not exists
Student johnny = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28)); // date not exists
System.out.println(john.hashCode());
System.out.println(johnny.hashCode());
System.out.println(sarah1.hashCode());
System.out.println();
cache.put(sarah1, 1);
cache.put(sarah2, 2);
cache.put(sarah3, 3);
System.out.println(new Date(sarah1.birthday));
System.out.println();
cache.put(john, 5);
System.out.println(cache.get(john));
System.out.println(cache.get(johnny));
cache.put(johnny, 7);
System.out.println(cache.get(john));
System.out.println(cache.get(johnny));
}
}
Para que serve o código hash?
Em primeiro lugar, os códigos hash ajudam os programas a serem executados mais rapidamente. Por exemplo, se compararmos dois objetos o1e o2de algum tipo, a operação o1.equals(o2)leva cerca de 20 vezes mais tempo do que o1.hashCode() == o2.hashCode(). Em Java, o princípio de hash está por trás de algumas coleções populares, como HashMap , HashSet e HashTable .
Conclusão
Todo objeto Java possui os métodos hashCode() e equals() herdados da classe Object . Para obter um bom mecanismo de igualdade de trabalho, é melhor sobrescrever os métodos hashcode() e equals() para suas próprias classes. O uso de hashcodes torna os programas mais rápidos.
GO TO FULL VERSION