Java génériques Paire<String, String> stockée dans la table de hachage pas de la récupération de la clé->valeur correctement
Voici Pair.java
import java.lang.*;
import java.util.*;
public class Pair<TYPEA, TYPEB> implements Comparable< Pair<TYPEA, TYPEB> > {
protected final TYPEA Key_;
protected final TYPEB Value_;
public Pair(TYPEA key, TYPEB value) {
Key_ = key;
Value_ = value;
}
public TYPEA getKey() {
return Key_;
}
public TYPEB getValue() {
return Value_;
}
public String toString() {
System.out.println("in toString()");
StringBuffer buff = new StringBuffer();
buff.append("Key: ");
buff.append(Key_);
buff.append("\tValue: ");
buff.append(Value_);
return(buff.toString() );
}
public int compareTo( Pair<TYPEA, TYPEB> p1 ) {
System.out.println("in compareTo()");
if ( null != p1 ) {
if ( p1.equals(this) ) {
return 0;
} else if ( p1.hashCode() > this.hashCode() ) {
return 1;
} else if ( p1.hashCode() < this.hashCode() ) {
return -1;
}
}
return(-1);
}
public boolean equals( Pair<TYPEA, TYPEB> p1 ) {
System.out.println("in equals()");
if ( null != p1 ) {
if ( p1.Key_.equals( this.Key_ ) && p1.Value_.equals( this.Value_ ) ) {
return(true);
}
}
return(false);
}
public int hashCode() {
int hashCode = Key_.hashCode() + (31 * Value_.hashCode());
System.out.println("in hashCode() [" + Integer.toString(hashCode) + "]");
return(hashCode);
}
}
Voici les cas de test:
import java.lang.*;
import java.util.*;
import junit.framework.*;
public class PairTest extends TestCase {
public void testPair() {
String key = new String("key");
String value = new String("asdf");
Pair<String, String> pair = new Pair<String, String>( key, value );
assertTrue( pair.getKey().equals( key ) );
assertTrue( pair.getValue().equals( value ) );
assertTrue( pair.equals( new Pair<String, String>(key, value)) );
}
public void testPairCollection() {
HashMap< Pair<String, String>, String> hm1 = new HashMap<Pair<String,String>, String>();
Pair<String, String> p1 = new Pair<String, String>("Test1", "Value1");
hm1.put(p1, "ONE");
Pair<String, String> p2 = new Pair<String, String>("Test1", "Value2");
hm1.put(p2, "TWO");
Pair<String, String> p3 = new Pair<String, String>("Test2", "Value1");
hm1.put(p3, "THREE");
Pair<String, String> p4 = new Pair<String, String>("Test2", "Value2");
hm1.put(p4, "FOUR");
Pair<String, String> p5 = new Pair<String, String>("Test3", "Value1");
hm1.put(p5, "FIVE");
Pair<String, String> p6 = new Pair<String, String>("Test3", "Value2");
hm1.put(p6, "SIX");
Pair<String, String> p7 = new Pair<String, String>("Test3", "Value3");
hm1.put(p7, "SEVEN");
assertTrue( hm1.size() == 7 );
Pair<String, String> pSrch = new Pair<String, String>("Test3", "Value3");
assertTrue( p7.equals(pSrch) );
assertTrue( pSrch.equals(p7) );
assertTrue( p7.hashCode() == pSrch.hashCode() );
assertTrue( 0 == p7.compareTo( pSrch ) );
assertTrue( 0 == pSrch.compareTo(p7) );
System.out.println("starting containsKey search");
assertTrue( hm1.containsKey( p7 ) );
System.out.println("starting containsKey search2");
assertTrue( hm1.containsKey( pSrch ) );
System.out.println("finishing containsKey search");
String result = hm1.get( pSrch );
assertTrue( null != result );
assertTrue( 0 == result.compareTo("SEVEN"));
}
}
Voici mon problème, le dernier hm1.containsKey appel (j'ai naïvement attendre le retour de la valeur stockée où Pair<"Trois", "Trois"> est vrai que je devrais obtenir une Chaîne de caractères avec une valeur de "SEPT". Voici le résultat:
Running in equals()
in hashCode() [1976956095]
in hashCode() [1976956126]
in hashCode() [1976956096]
in hashCode() [1976956127]
in hashCode() [1976956097]
in hashCode() [1976956128]
in hashCode() [1976956159]
in equals()
in equals()
in hashCode() [1976956159]
in hashCode() [1976956159]
in compareTo()
in equals()
in compareTo()
in equals()
starting containsKey search
in hashCode() [1976956159]
starting containsKey search2
in hashCode() [1976956159] <--- Bug here?
Never reaches
String result = hm1.get( pSrch );
Est donc à la fois p7.hashCode() et pSrch.hashCode() sont égaux et p7.equals(pSrch) et pSrch.equals(p7), et hm1.containsValue(p7) == vrai, je m'attends à ce hm1.containsValue(pSrch) serait également de retour vrai, mais il ne le fait pas. Ce qui me manque?
OriginalL'auteur Chris K | 2009-04-22
Vous devez vous connecter pour publier un commentaire.
Vous devez remplacer la
equals
méthode de lajava.lang.Object
classe.Au lieu de cela, vous avez surchargé la méthode avec une version supplémentaire qui prend un
Pair
. Totalement différente de la méthode, qui n'est jamais appelée. Remplacer votreequals
avec quelque chose comme ceci:Pour éviter ce genre d'erreur, utilisez la
@Override
annotation sur les méthodes que vous avez l'intention d'agir comme des remplacements. Vous obtiendrez une erreur de compilation quand ils ne le font pas.Je suis le posteur d'origine, je ne suis pas sûr que je suis sur la mauvaise noms bits? Que dans equals() qui p1.Key_ pourrait être nulle? Oui, c'est exact. Merci pour cela.
Vous voulez probablement pour tester si cela.getClass() == o.getClass(), au lieu de simplement instanceof, sauf si vous voulez vraiment une sous-classe de la Paire (éventuellement) être égale à une instance de la Paire. Cela pourrait conduire à votre equals() de la mise en œuvre n'étant pas réflexive - ce qui signifie qu'il est possible pour une.equals(b) != b.est égal à(a). Ce serait violer le dit contrat de l'Objet.equals().
Ou faire la classe, ou au moins les méthodes pertinentes,
final
. Les Classes doivent être soigneusement conçues pour l'extensibilité. Ce n'est pas (sans-papiers de l'auto-utilisation de méthodes non-défini " les améliorations apportées à des égaux, etc). Donc le choix le plus sûr est de le rendre définitif. La Composition au cours de l'héritage.OriginalL'auteur erickson
Vous avez sans doute remarqué qu'il n'imprime pas "dans equals()" après "de départ containsKey search2". Vous pouvez également déboguer dans HashMap pour voir que .méthode equals() est appelée et renvoie la valeur false. C'est parce que
ne remplace PAS
défini en java.lang.Objet
Modifier votre code pour
et il fonctionne. Vous pouvez éviter ces bugs dans l'avenir en mettant @Override annotation avant la méthode que vous pensez que vous êtes primordial. Si vous n'êtes pas réellement remplaçant, le compilateur va vous le dire. Cette
causes d'erreur de compilation. Cette
ne le fait pas. Aussi bonne IDE Intellij IDEA par exemple) indique les méthodes qui sont redéfinies.
OriginalL'auteur Pavel Feldman