2009-04-22 50 views
3

這裏的Pair.javaJava泛型對<String,字符串>存儲在HashMap中沒有檢索鍵 - >值正確

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); 
    } 
} 

這裏的測試用例:

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")); 

    } 
} 

這裏是我的問題,最後HM1 .containsKey調用應該(我天真的期望)返回值存儲在一對<「三」,「三」>是真實的 - 我應該得到一個字符串值爲「七」。下面是輸出:

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); 

所以既p7.hashCode()和pSrch.hashCode()是相等的,p7.equals(pSrch)和pSrch.equals(P7),並且hm1.containsValue(P7) == true,我期望hm1.containsValue(pSrch)也會返回true,但它不會。我錯過了什麼?

回答

24

您需要覆蓋 類的equals方法。

取而代之的是,您有超載該方法的附加版本需要Pair。完全不同的方法,永遠不會被調用。像這樣的東西替換您equals

@Override 
public boolean equals(Object o) { 
    System.out.println("in equals()"); 
    if (o instanceof Pair) { 
    Pair<?, ?> p1 = (Pair<?, ?>) o; 
    if (p1.Key_.equals(this.Key_) && p1.Value_.equals(this.Value_)) { 
     return(true); 
    } 
    } 
    return(false); 
} 

爲了避免這種錯誤,請您打算作爲替代方法@Override註解。如果沒有,你會得到一個編譯時錯誤。

+0

Key_和Value_可能爲空。 (不正確的名字,btw原始提問者。) – 2009-04-22 22:30:44

+0

我是原始的海報,我不知道我跟隨不正確的名字位?在equals()中,p1.Key_可能爲null?是,對的。感謝那。 – 2009-04-22 23:07:14

5

您應該注意到它在「開始containsKey search2」之後不打印「in equals()」。你也可以調試到HashMap來看到.equals()方法被調用並返回false。這是因爲

public boolean equals(Pair<TYPEA, TYPEB> p1) 

不會覆蓋

public boolean equals(Object obj) 

在java.lang.Object中

定義

更改您的代碼

public boolean equals(Object obj) { 
    if (!(obj instanceof Pair)) return false; 
    Pair p1 = (Pair) obj; 

和它的作品。您可以通過在您認爲自己重寫的方法之前放置@Override註釋來避免此類錯誤。如果你實際上沒有覆蓋它,編譯器會告訴你。這

@Override public boolean equals(Pair<TYPEA, TYPEB> p1) 

導致編譯錯誤。這

@Override public boolean equals(Object obj) 

沒有。另外好的IDE(例如Intellij IDEA)顯示哪些方法被覆蓋。

相關問題