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.
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() . En el caso de nuestro ejemplo tenemos el siguiente código:
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 :
importjava.util.Date;publicclassStudent{String surname;String name;String secondName;Long birthday;// Long instead of long is used by Gson/Jackson json parsers and various orm databasespublicStudent(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@OverridepublicinthashCode(){//TODO: check for nulls//return surname.hashCode() ^ name.hashCode() ^ secondName.hashCode() ^ (birthday.hashCode());return(surname + name + secondName + birthday).hashCode();}@Overridepublicbooleanequals(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:
importjava.util.Date;importjava.util.HashMap;importjava.util.Hashtable;publicclassMain{staticHashMap<Student,Integer> cache =newHashMap<Student,Integer>();// <person, targetPriority>publicstaticvoidmain(String[] args){Student sarah1 =newStudent("Sarah","Connor","Jane",null);Student sarah2 =newStudent("Sarah","Connor","Jane",newDate(1970,01-1,01));Student sarah3 =newStudent("Sarah","Connor","Jane",newDate(1959,02-1,28));// date not existsStudent john =newStudent("John","Connor","Kyle",newDate(1985,02-1,28));// date not existsStudent johnny =newStudent("John","Connor","Kyle",newDate(1985,02-1,28));// date not existsSystem.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(newDate(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.