Principe de hachage
Tout d'abord, avant de définir le hashcode Java, nous devons comprendre ce qu'est le hachage et à quoi il sert. Le hachage est un processus d'application d'une fonction de hachage à certaines données. Une fonction de hachage n'est qu'une fonction mathématique. Ne vous inquiétez pas pour ça !
« Mathématique » ne veut pas toujours dire « compliqué ». Ici, cela signifie seulement que nous avons des données et une certaine règle qui mappe les données dans un ensemble de caractères (code). Par exemple, il pourrait s'agir d'un chiffrement hexadécimal. Nous avons des données de n'importe quelle taille à l'entrée et nous leur appliquons une fonction de hachage.
En sortie, nous obtenons des données de taille fixe, disons 32 caractères. Habituellement, ce type de fonction convertit un gros morceau de données en une petite valeur entière. Le résultat de ce travail de fonction est appelé un code de hachage. Les fonctions de hachage sont largement utilisées en cryptographie, ainsi que dans d'autres domaines. Les fonctions de hachage peuvent être différentes,
- Un objet particulier a un hashcode particulier.
- Si deux objets sont égaux, leurs hashcodes sont les mêmes. L'inverse n'est pas vrai.
- Si les codes de hachage sont différents, alors les objets ne sont pas égaux à coup sûr.
- Différents objets peuvent avoir le même code de hachage. Cependant, c'est un événement très improbable. À ce stade, nous avons une collision, une situation où nous pouvons perdre des données.
La fonction de hachage "appropriée" minimise la probabilité de collisions.
Code de hachage en Java
En Java, la fonction de hachage est généralement connectée à
la méthode hashCode() . Précisément, le résultat de l'application d'une fonction de hachage à un objet est un hashcode. Chaque objet Java a un code de hachage. En général, Hash Code est un nombre calculé par la méthode
hashCode() de la
Object
classe.
Habituellement, les programmeurs remplacent cette méthode pour leurs objets ainsi que pour
hashCode() la méthode
equals() pour un traitement plus efficace de données spécifiques. La méthode
hashCode() renvoie une valeur int (4 octets), qui est une représentation numérique de l'objet. Ce hashcode est utilisé, par exemple, par les collections pour un stockage plus efficace des données et, par conséquent, un accès plus rapide à celles-ci.
Par défaut, le
hashCode()fonction pour un objet renvoie le numéro de la cellule mémoire où l'objet est stocké. Par conséquent, si aucune modification n'est apportée au code de l'application, la fonction doit renvoyer la même valeur. Si le code change légèrement, la valeur du hashcode change également. À quoi sert le hashcode en Java ? Tout d'abord, les hashcodes Java aident les programmes à s'exécuter plus rapidement. Par exemple, si nous comparons deux objets
o1
et
o2
d'un certain type, l'opération
o1.equals(o2)
prend environ 20 fois plus de temps que
o1.hashCode() == o2.hashCode()
.
Java est égal à ()
Dans la classe parent
Object
, avec la méthode
hashCode() , il y a aussi
equals() , la fonction qui est utilisée pour vérifier l'égalité de deux objets. L'implémentation par défaut de cette fonction vérifie simplement les liens de deux objets pour leur équivalence.
equals() et
hashCode() ont leur contrat, donc si vous remplacez l'un d'eux, vous devez remplacer l'autre, afin de ne pas rompre ce contrat.
Implémentation de la méthode hashCode()
Exemple
Créons une classe
Character avec un champ —
name . Après cela, nous créons deux objets de la classe
Character ,
character1 et
character2 et leur donnons le même nom. Si nous utilisons les
hashCode() et
equals() par défaut de la classe
Object , nous obtiendrons certainement des objets différents et non égaux. C'est ainsi que fonctionne le hashcode en Java.
Ils auront des hashcodes différents car ils se trouvent dans des cellules de mémoire différentes et le résultat de l'opération
equals() sera faux.
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));
}
}
Le résultat de l'exécution du programme:
Arnold
1595428806
Arnold
1072408673
false
Deux nombres à 10 chiffres dans la console sont des hashcodes. Que se passe-t-il si nous voulons avoir des objets égaux s'ils ont les mêmes noms ? Que devrions nous faire? La réponse : nous devrions remplacer les méthodes
hashCode() et
equals() de la classe
Object pour notre classe
Character . Nous pourrions le faire automatiquement dans IDEA IDE, appuyez simplement sur
alt + insert sur votre clavier et choisissez
Generate -> equals() and hashCode() .
Dans le cas de notre exemple, nous avons le code suivant :
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));
}
}
Le résultat de l'exécution de ce code:
Arnold
1969563338
Arnold
1969563338
true
Alors maintenant, le programme identifie nos objets comme égaux et ils ont les mêmes hashcodes.
Exemple de hashcode Java:
Votre propre hashCode() et equals()
Vous pouvez également créer vos propres réalisations
equals() et
hashCode() , mais soyez prudent et n'oubliez pas de minimiser les collisions de hashcode. Voici un exemple de nos propres méthodes
hashCode() et
equals() dans la classe
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));
}
}
Et la classe
principale pour démontrer leur travail:
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));
}
}
A quoi sert le hashcode?
Tout d'abord, les hashcodes aident les programmes à fonctionner plus rapidement. Par exemple, si nous comparons deux objets
o1
et
o2
d'un certain type, l'opération
o1.equals(o2)
prend environ 20 fois plus de temps que o1.hashCode() == o2.hashCode(). En Java, le principe de hachage est derrière certaines collections populaires, telles que
HashMap ,
HashSet et
HashTable.
Conclusion
Chaque objet Java possède les méthodes
hashCode() et
equals() héritées de la classe Object . Pour obtenir un bon mécanisme d'égalité de travail, vous feriez mieux de remplacer les méthodes
hashcode() et
equals() pour vos propres classes. L'utilisation de hashcodes accélère l'exécution des programmes.
GO TO FULL VERSION