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
Object
clase. 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
o1
y
o2
de 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 () - 2]()
En 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;
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();
}
@Override
public int 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>();
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));
Student john = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28));
Student johnny = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28));
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
o1
y
o2
de 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.
GO TO FULL VERSION