CodeGym /Blog Java /Random-ES /Código hash de Java()
Autor
Oleksandr Miadelets
Head of Developers Team at CodeGym

Código hash de Java()

Publicado en el grupo Random-ES

Principio hash

En primer lugar, antes de definir el código hash de Java, debemos comprender qué es el hashing y para qué sirve. Hashing es un proceso de aplicar una función hash a algunos datos. Una función hash es solo una función matemática. ¡No te preocupes por esto! “Matemático” no siempre significa “complicado”. Aquí solo significa que tenemos algunos datos y una cierta regla que mapea los datos en un conjunto de caracteres (código). Por ejemplo, podría ser un cifrado hexadecimal. Tenemos algunos datos de cualquier tamaño en la entrada y le aplicamos una función hash. En la salida, obtenemos datos de tamaño fijo, digamos, 32 caracteres. Por lo general, ese tipo de función convierte una gran cantidad de datos en un pequeño valor entero. El resultado del trabajo de esta función se denomina código hash. Las funciones hash se usan ampliamente en criptografía, y también en otras áreas. Las funciones hash pueden ser diferentes,
  • Un objeto particular tiene un código hash particular.
  • Si dos objetos son iguales, sus códigos hash son los mismos. Lo opuesto no es verdad.
  • Si los códigos hash son diferentes, entonces los objetos no son iguales con seguridad.
  • Diferentes objetos pueden tener el mismo código hash. Sin embargo, es un evento muy poco probable. En este punto, tenemos una colisión, una situación en la que podemos perder datos.
La función hash "adecuada" minimiza la probabilidad de colisiones.

Código hash en Java

En Java, la función hash generalmente está conectada al método hashCode() . Precisamente, el resultado de aplicar una función hash a un Objeto es un código hash. Cada objeto Java tiene un código hash. En general, Hash Code es un número calculado por el método hashCode() de la Objectclase. Por lo general, los programadores anulan este método para sus objetos, así como el método equals() relacionado con hashCode() para un procesamiento más eficiente de datos específicos. El método hashCode() devuelve un valor int (4 bytes), que es una representación numérica del objeto. Este código hash es utilizado, por ejemplo, por las colecciones para un almacenamiento de datos más eficiente y, en consecuencia, un acceso más rápido a ellos. Por defecto, el hashCode()función para un objeto devuelve el número de la celda de memoria donde se almacena el objeto. Por lo tanto, si no se realizan cambios en el código de la aplicación, la función debería devolver el mismo valor. Si el código cambia ligeramente, el valor del código hash también cambia. ¿Para qué se usa el código hash en Java? En primer lugar, los códigos hash de Java ayudan a que los programas se ejecuten más rápido. Por ejemplo, si comparamos dos objetos o1y o2de algún tipo, la operación o1.equals(o2)tarda unas 20 veces más que o1.hashCode() == o2.hashCode().

Java es igual ()

En la clase padre Object, junto con el método hashCode() , también está equals() , la función que se usa para verificar la igualdad de dos objetos. La implementación predeterminada de esta función simplemente verifica los enlaces de dos objetos para determinar su equivalencia. equals() y hashCode() tienen su contrato, por lo que si anula uno de ellos, debe anular el otro para no romper este contrato.

Implementando el método hashCode()

Ejemplo

Vamos a crear un carácter de clase con un campo: nombre . Después de eso, creamos dos objetos de la clase Character , character1 y character2 y les asignamos el mismo nombre. Si usamos el hashCode() y equals() predeterminados de la clase Object , definitivamente obtendremos objetos diferentes, no iguales. Así es como funciona el código hash en Java. Tendrán diferentes códigos hash porque están en diferentes celdas de memoria y el resultado de la operación 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));
    }
}
El resultado de ejecutar el programa:

Arnold
1595428806
Arnold
1072408673
false
Dos números de 10 dígitos en la consola son códigos hash. ¿Qué pasa si queremos tener objetos iguales si tienen los mismos nombres? ¿Qué debemos hacer? La respuesta: debemos anular los métodos hashCode() y equals() de la clase Object para nuestra clase Character . Podríamos hacerlo automáticamente en IDEA IDE, simplemente presione alt + insertar en su teclado y elija Generar -> equals() y hashCode() . ¿Qué es Java hashCode () - 2En el caso de nuestro ejemplo tenemos el siguiente 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));
    }
}
El resultado de ejecutar este código:

Arnold
1969563338
Arnold
1969563338
true
Así que ahora el programa identifica nuestros objetos como iguales y tienen los mismos códigos hash.

Ejemplo de código hash de Java:

Tu propio hashCode() y equals()

También puede crear sus propias realizaciones de equals() y hashCode() , pero tenga cuidado y recuerde minimizar las colisiones de hashcode. Aquí hay un ejemplo de nuestros propios métodos hashCode() y equals() en la clase Student :

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));
   }
}
Y la clase principal para demostrar su trabajo:

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 qué se usa el código hash?

En primer lugar, los códigos hash ayudan a que los programas se ejecuten más rápido. Por ejemplo, si comparamos dos objetos o1y o2de algún tipo, la operación o1.equals(o2)tarda unas 20 veces más que o1.hashCode() == o2.hashCode(). En Java, el principio de hash está detrás de algunas colecciones populares, como HashMap , HashSet y HashTable .

Conclusión

Cada objeto Java tiene los métodos hashCode() y equals() heredados de la clase Object . Para obtener un buen mecanismo de igualdad de trabajo, será mejor que anule los métodos hashcode() y equals() para sus propias clases. El uso de códigos hash hace que los programas se ejecuten más rápido.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION