package aaa;import java.util.*;
class Student{
int num;
String name;
public Student(int num,String name){
this.num=num;
this.name=name;
}
public int hashcode(){
return this.name.hashCode()*num;
}
public boolean equals(Object o){
Student s=(Student)o;
return num==s.num&&name.equals(s.name);
}
public String toString(){
return this.num+":"+this.name;
}
}
public class HashSetText{
public static void main(String args[]){
HashSet<Student> hs=new HashSet<Student>();
hs.add(new Student(1,"zhangsan"));
hs.add(new Student(2,"lisi"));
hs.add(new Student(3,"wangwu"));
hs.add(new Student(1,"zhangsan"));
System.out.println(hs);
}
}
/*为什么这个程序输出结果是:2:lisi 1:zhangsan 3:wangwu 1:zhangsan.
我想问的是为什么1:zhangsan这个重复的东西也打印出来了,我在student类中覆写了hashcode和equals方法啊?这是怎么回事??
另外我在网上看到有人说了这样一段话:
3.这里我们首先要明白一个问题: 
equals()相等的两个对象,hashcode()一定相等; 
equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。 
反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。解释下第3点的使用范围,我的理解是在object、String等类中都能使用。在object类中,hashcode()方法是本地方法,返回的是对象的地址值,而object类中的equals()方法比较的也是两个对象的地址值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了;在String类中,equals()返回的是两个对象内容的比较,当两个对象内容相等时, 
Hashcode()方法根据String类的重写(第2点里面已经分析了)代码的分析,也可知道hashcode()返回结果也会相等。以此类推,可以知道Integer、Double等封装类中经过重写的equals()和hashcode()方法也同样适合于这个原则。当然没有经过重写的类,在继承了object类的equals()和hashcode()方法后,也会遵守这个原则。 请高手评论一下以上这段话,你觉得他说的对不对,你是怎样理解的??*/

解决方案 »

  1.   

    兄弟你的hashcode方法名字写错了
    应该是public int hashCode() {
    return this.name.hashCode() * num;
    }
      

  2.   

    equals()位true,hashcode()一定相等; 
    hashcode()相等时,equals() 一定为truehashCode 的常规协定是: 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。 
    如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。 
    如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。 
    至于为什么,你要是知道hashcode,哈希表是神马,什么十字链表 什么再哈希法 blah blah
      

  3.   

    1、equals()返回true的两个对象,hashCode()应该返回一样的值,为啥呢?如果不一样的话,集合框架中很多的容器的行为就比较奇怪~~~
    2、hashCode()返回相同的值,两个对象不一定相等(即equals()不一定返回true),比如最SB的方法就重写hashCode()方法让它返回一样的值,这点其实容易想通,数据结构中说到哈希表的时候不是说出现冲突吗?就是不同的东西映射到一个值了
    3、hashCode()返回不一样的值的两个对象,equals()一定返回false
    这些东西都是一些约定,不遵守的话代码的行为比较奇怪,结果不是我们想的那样~
      

  4.   

    我发现要用HashSet和TreeSet实现动态增加数组的元素,都必须在被操作类中实现hashcode()和equals()方法,缺一不可,进过楼上三位同志的讨论,让我对为什么必须同时具备这两个方法有所了解,但关于更细节的东西,我还不是很懂,(貌似楼上三位意见都有分歧!!)希望更多的人参与讨论。
      

  5.   

    看我写的就好了,其他忽略~~也可以读一下《Effective Java》
      

  6.   

    楼主可以看看底层代码就会明白equals和hashCode的用法,代码注释出已经写得十分清楚了,关于这两个方法的一些约定。
    //截个看看,个人感觉还是看底层来个直接明了,不会有任何疑问。
         * <li>Whenever it is invoked on the same object more than once during 
         *     an execution of a Java application, the <tt>hashCode</tt> method 
         *     must consistently return the same integer, provided no information 
         *     used in <tt>equals</tt> comparisons on the object is modified.
         *     This integer need not remain consistent from one execution of an
         *     application to another execution of the same application. 
         * <li>If two objects are equal according to the <tt>equals(Object)</tt>
         *     method, then calling the <code>hashCode</code> method on each of 
         *     the two objects must produce the same integer result. 
         // ...
      

  7.   

    老师给我们将说一般重写equals方法时候,就要重写hashcode 方法
    检查下,你写的equals和hashcode 方法写得对不对,要是都写对了,就不会出现重复的情况了
    本来想改正下的,突然发现自己好久没写集合这块的的代码了,呵呵,得好好复习下,再来讨论啊,等高手来指教,呵呵
      

  8.   

    一般重写equals方法时候,就要重写hashcode 方法