CodeGym /Blogue Java /Random-PT /Java hashCode()
John Squirrels
Nível 41
San Francisco

Java hashCode()

Publicado no grupo Random-PT

Princípio do hash

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() . O que é Java hashCode() - 2No 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.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION