$ java -version
java version "10.0.2" 2018-07-17
Lorsque je définis ma propre classe en Java, ma propre collection de classes ne fonctionne pas correctement à moins que je ne remplace correctement ʻequalset
hashCode`.
Cette fois, j'ai défini une classe originale simple et généré ʻequals et
hashCode` en utilisant un IDE appelé IntelliJ, mais j'en étais accro, donc je vais le partager.
DistanceToNode
et j'ai fait ce qui suit pour cette classe:
--Ajouter des éléments dans Set-> Ajouter un autre élément-> Supprimer le premier élément ajouté
--Créez deux instances de classe avec la même valeur et comparez-les avec des égalesimport java.util.*;
public class TestEqualsOld {
public static void main(String[] args) {
Set<DistanceToNode> someSet = new HashSet<>();
someSet.add(new DistanceToNode(1, 2));
System.out.println("actual = " + someSet.size() + " expected = 1");
someSet.add(new DistanceToNode(2, 3));
System.out.println("actual = " + someSet.size() + " expected = 2");
someSet.remove(new DistanceToNode(1, 2));
System.out.println("actual = " + someSet.size() + " expected = 1");
boolean flag = new DistanceToNode(3, 4).equals(new DistanceToNode(3, 4));
System.out.println("actual = " + flag + " expected = true");
}
}
class DistanceToNode {
private int dist;
private int index;
public DistanceToNode(int dist, int index) {
this.dist = dist;
this.index = index;
}
public int getDist() {
return dist;
}
public int getIndex() {
return index;
}
}
et
hashCode`, la méthode de la classe Object, qui est une super-classe, est utilisée à la place pour déterminer si les références sont égales, pas si les valeurs sont égales. y a-t-il.actual = 1 expected = 1
actual = 2 expected = 2
actual = 2 expected = 1
actual = false expected = true
et
hashCode` du code précédent en utilisant IntelliJ. Placez le curseur sur la classe, cliquez avec le bouton droit de la souris et sélectionnez Générer> equals () et hashCode (). J'ai choisi "IntelliJ Default" qui est sélectionné par défaut comme modèle. Ensuite, le code suivant a été généré.import java.util.*;
public class TestEqualsOld {
public static void main(String[] args) {
Set<DistanceToNode> someSet = new HashSet<>();
someSet.add(new DistanceToNode(1, 2));
System.out.println("actual = " + someSet.size() + " expected = 1");
someSet.add(new DistanceToNode(2, 3));
System.out.println("actual = " + someSet.size() + " expected = 2");
someSet.remove(new DistanceToNode(1, 2));
System.out.println("actual = " + someSet.size() + " expected = 1");
boolean flag = new DistanceToNode(3, 4).equals(new DistanceToNode(3, 4));
System.out.println("actual = " + flag + " expected = true");
}
}
class DistanceToNode {
private int dist;
private int index;
public DistanceToNode(int dist, int index) {
this.dist = dist;
this.index = index;
}
public int getDist() {
return dist;
}
public int getIndex() {
return index;
}
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
if (!super.equals(object)) return false;
DistanceToNode that = (DistanceToNode) object;
return dist == that.dist &&
index == that.index;
}
public int hashCode() {
return Objects.hash(super.hashCode(), dist, index);
}
}
,
hashCode` d'IntelliJ?actual = 1 expected = 1
actual = 2 expected = 2
actual = 2 expected = 1
actual = false expected = true
―― J'ai eu mal à la tête pendant quelques jours ici, mais si vous regardez de près le code généré par IntelliJ, ʻequalset
hashCode` utilisent les méthodes super.equals et super.hashCode en interne !!! J'ai pensé que cela fonctionnerait si je le réécrivais pour qu'il n'utilise pas super.equals ou super.hashCode, j'ai donc modifié le code comme suit. (J'ai également changé le nom de la classe.)
import java.util.*;
public class TestEquals {
public static void main(String[] args) {
Set<DistanceToNode> someSet = new HashSet<>();
someSet.add(new DistanceToNode(1, 2));
System.out.println(someSet.size());
someSet.add(new DistanceToNode(2, 3));
System.out.println(someSet.size());
someSet.remove(new DistanceToNode(1, 2));
System.out.println(someSet.size());
boolean flag = new DistanceToNode(3, 4).equals(new DistanceToNode(3, 4));
System.out.println(flag);
}
}
class DistanceToNode {
private int dist;
private int index;
public DistanceToNode(int dist, int index) {
this.dist = dist;
this.index = index;
}
public int getDist() {
return dist;
}
public int getIndex() {
return index;
}
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
// if (!super.equals(object)) return false;
DistanceToNode distanceToNode = (DistanceToNode) object;
return dist == distanceToNode.dist &&
index == distanceToNode.index;
}
@Override
public int hashCode() {
int result = 31;
result = 31 * result + dist;
result = 31 * result + index;
return result;
// return Objects.hash(super.hashCode(), dist, index);
}
}
actual = 1 expected = 1
actual = 2 expected = 2
actual = 1 expected = 1
actual = true expected = true
――IntelliJ est pratique, mais j'ai appris une leçon précieuse: il ne faut pas être aveugle et parfois il faut utiliser sa propre tête. ――Je me suis demandé pourquoi un tel code est créé lorsque IntelliJ génère automatiquement des valeurs égales et hashCode, et y a-t-il une raison raisonnable?