在thinking in java中hashmap中说,如果key是自定义的类,那么必须得重载equals()和hashcode()两个方法,书中说的我没理解太清楚,如果要比较key是否相等,得同时使用这两个函数?还是使用随便其中一个就可以了?对于set,如果存入的元素是自定义的类,是否也得重载equalis()和hashcode()这两个函数?

解决方案 »

  1.   

    同时使用,hashcode先判断比如ab和ac,可以自定义hashcode比较首字母a,然后再equals自定义类最好是重载
      

  2.   

        /**
         * Returns a hash code value for the object. This method is 
         * supported for the benefit of hashtables such as those provided by 
         * <code>java.util.Hashtable</code>. 
         * <p>
         * The general contract of <code>hashCode</code> is: 
         * <ul>
         * <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. 
         * <li>It is <em>not</em> required that if two objects are unequal 
         *     according to the {@link java.lang.Object#equals(java.lang.Object)} 
         *     method, then calling the <tt>hashCode</tt> method on each of the 
         *     two objects must produce distinct integer results.  However, the 
         *     programmer should be aware that producing distinct integer results 
         *     for unequal objects may improve the performance of hashtables.
         * </ul>
         * <p>
         * As much as is reasonably practical, the hashCode method defined by 
         * class <tt>Object</tt> does return distinct integers for distinct 
         * objects. (This is typically implemented by converting the internal 
         * address of the object into an integer, but this implementation 
         * technique is not required by the 
         * Java<font size="-2"><sup>TM</sup></font> programming language.)
         *
         * @return  a hash code value for this object.
         * @see     java.lang.Object#equals(java.lang.Object)
         * @see     java.util.Hashtable
         */
        public native int hashCode();    /**
         * Indicates whether some other object is "equal to" this one.
         * <p>
         * The <code>equals</code> method implements an equivalence relation
         * on non-null object references:
         * <ul>
         * <li>It is <i>reflexive</i>: for any non-null reference value
         *     <code>x</code>, <code>x.equals(x)</code> should return
         *     <code>true</code>.
         * <li>It is <i>symmetric</i>: for any non-null reference values
         *     <code>x</code> and <code>y</code>, <code>x.equals(y)</code>
         *     should return <code>true</code> if and only if
         *     <code>y.equals(x)</code> returns <code>true</code>.
         * <li>It is <i>transitive</i>: for any non-null reference values
         *     <code>x</code>, <code>y</code>, and <code>z</code>, if
         *     <code>x.equals(y)</code> returns <code>true</code> and
         *     <code>y.equals(z)</code> returns <code>true</code>, then
         *     <code>x.equals(z)</code> should return <code>true</code>.
         * <li>It is <i>consistent</i>: for any non-null reference values
         *     <code>x</code> and <code>y</code>, multiple invocations of
         *     <tt>x.equals(y)</tt> consistently return <code>true</code>
         *     or consistently return <code>false</code>, provided no
         *     information used in <code>equals</code> comparisons on the
         *     objects is modified.
         * <li>For any non-null reference value <code>x</code>,
         *     <code>x.equals(null)</code> should return <code>false</code>.
         * </ul>
         * <p>
         * The <tt>equals</tt> method for class <code>Object</code> implements 
         * the most discriminating possible equivalence relation on objects; 
         * that is, for any non-null reference values <code>x</code> and
         * <code>y</code>, this method returns <code>true</code> if and only
         * if <code>x</code> and <code>y</code> refer to the same object
         * (<code>x == y</code> has the value <code>true</code>).
         * <p>
         * Note that it is generally necessary to override the <tt>hashCode</tt>
         * method whenever this method is overridden, so as to maintain the
         * general contract for the <tt>hashCode</tt> method, which states
         * that equal objects must have equal hash codes. 
         *
         * @param   obj   the reference object with which to compare.
         * @return  <code>true</code> if this object is the same as the obj
         *          argument; <code>false</code> otherwise.
         * @see     #hashCode()
         * @see     java.util.Hashtable
         */
        public boolean equals(Object obj) {
    return (this == obj);
        }
      

  3.   

    如果要比较key是否相等,要同时使用这两个函数!因为自定义的类的hashcode()方法继承于Object类,其hashcode码为默认的内存地址,这样即便有相同含义的两个对象,比较也是不相等的,例如,生成了两个“羊”对象,正常理解这两个对象应该是相等的,但如果你不重写hashcode()方法的话,比较是不相等的!set有HashSet和TreeSet,HashSet最好是要重写这两个方法了,TreeSet一般就不需要了水平有限,如有错误请改正
      

  4.   

    现在又有问题了,有些例子还要实现comparable接口的compareTo()方法,难道为了一个对象比较是否相等,需要equals, hashcode和compareTo三个方法?不是有点过于啰嗦了吗?
      

  5.   

    为了一个对象比较是否相等只需要实现comparable接口
    或者为该类写个比较器就可以了!其他的不用管。
      

  6.   


    所有带hash的例如HashMap,HashSet就表示你要重写hashcode方法。所有带Tree的,例如TreeSet,表示使用红黑树按次序放置。那么使用compareTo方法。关键看你要用什么。
      

  7.   

    呵呵,我以前也问过同样的问题。HashMap中的比较key是这样的,先求出key的hashcode(),比较其值是否相等,若相等再比较equals(),若相等则认为他们是相等的。若equals()不相等则认为他们不相等。如果只重写hashcode()不重写equals()方法,当比较equals()时只是看他们是否为同一对象(即进行内存地址的比较),所以必定要两个方法一起重写。HashMap用来判断key是否相等的方法,其实是调用了HashSet判断加入元素是否相等。
      

  8.   

    hashmap的内部是这样的每对key 和 value都变成一个新的对象,用key.hashcode()来生成一个散列吗,不同的key有可能生成相同的散列吗。有一个数组来,数组的index是生成的各个散列吗,而元素是一个list.把key/value对象放入对应的list中,由于散列码是可能重复的,所以一个list中可能有多个key/value 对象, 这些重复的对象就需要定义equals()来比较。
      

  9.   

    引用别人说的一段话哈~
    一般来说,如果你要把一个类的对象放入容器中,那么通常要为其重写equals()方法,让他们比较地址值而不是内容值。特别地,如果要把你的类的对象放入散列中,那么还要重写hashCode()方法;要放到有序容器中,还要重写compareTo()方法。
    equals()相等的两个对象,hashcode()一定相等;
    equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。
    反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等我的理解哈,
    不同的key有可能是一样的code,所以需要再用equals来处理hash冲突,其实只要拿个equals也行,但是效率会降低
    在list对象中也存在同样的问题,也需要重写equals方法
    这些都是我的老师告诉我的,其实我在用arraylist的时候存储的比较简单,但是老师让我加一些附加信息,不重写的话,比较的是内存地址,那么如果你不断的new,它会认为是相同的