代码之家  ›  专栏  ›  技术社区  ›  Chris K

Java泛型对“字符串”、“字符串”存储在HASMAP中,不能正确检索关键字->值

  •  3
  • Chris K  · 技术社区  · 16 年前

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

    下面是测试用例:

    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调用应该(我天真地希望)返回存储在pair<“3”,“3”>为真的位置的值-我应该得到一个值为“7”的字符串。以下是输出:

    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,但它不会。我错过了什么?

    2 回复  |  直到 16 年前
        1
  •  24
  •   erickson    16 年前

    你需要 重写 这个 equals 方法从 java.lang.Object 班级。

    相反,你已经 超载 具有附加版本的方法 Pair . 完全不同的方法,永远不会被调用。取代你 等于 就这样:

    @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 要用作重写的方法的批注。如果没有,您将得到一个编译时错误。

        2
  •  5
  •   Pavel Feldman    16 年前

    您应该注意到,它不会在“starting 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 annotation放在您认为要覆盖的方法之前,可以避免将来出现此类错误。如果您实际上没有重写它,编译器会告诉您。这个

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

    导致编译错误。这个

    @Override public boolean equals( Object obj )
    

    没有。好的IDE(例如intellij-idea)也显示了哪些方法被重写。