3

这是对.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<"Three", "Three"> 为真的地方的值 - 我应该得到一个值为 "SEVEN" 的字符串。这是输出:

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,但事实并非如此。我错过了什么?

4

2 回答 2

24

您需要覆盖类中的equals方法java.lang.Object

相反,您已经用一个额外的版本重载了该方法,该版本需要一个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在您打算用作覆盖的方法上使用注释。如果没有,你会得到一个编译时错误。

于 2009-04-22T22:07:49.900 回答
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)也显示了哪些方法被覆盖。

于 2009-04-22T22:15:59.677 回答