现在的位置: 首页 > 综合 > 正文

Item8:改写equals的时候总是要改写hashCode

2012年08月14日 ⁄ 综合 ⁄ 共 2055字 ⁄ 字号 评论关闭
 

/**

 * 在改写equals的时候总是要改写hashCode,如果不这样的话,就会违反Object.hashCode的通用约定,

 * 导致这个类无法与所有基于散列值的集合类结合在一起正常工作,包括HashMap,HashSetHashtable

 * hashCode的约定内容:

 * hashCode()返回该对象的哈希码值。支持该方法是为哈希表提供一些优点.

 * (1)Java应用程序执行期间,在同一对象上多次调用hashCode方法时,必须一致地返回相同的整数,

 *    前提是对象上equals比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的

 *    另一次执行,该整数无需保持一致。

 * (2)如果根据equals(Object)方法,两个对象是相等的,那么在两个对象中的每个对象上调用

 *    hashCode方法都必须生成相同的整数结果。(不改写hashCode违反的关键是本条)

 * (3)以下情况不是必需的:如果根据equals(java.lang.Object)方法,两个对象不相等,那么在两个对象

 *    中的任一对象上调用hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生

 *    成不同整数结果可以提高哈希表的性能。 *

 */

public class PhoneNumber {

    private final short areaCode;

    private final short exchange;

    private final short extension;

 

    public PhoneNumber(int areaCode, int exchange,

                       int extension) {

        rangeCheck(areaCode,   999, "area code");

        rangeCheck(exchange,   999, "exchange");

        rangeCheck(extension, 9999, "extension");

        this.areaCode  = (short) areaCode;

        this.exchange  = (short) exchange;

        this.extension = (short) extension;

    }

 

    private static void rangeCheck(int arg, int max,

                                   String name) {

        if (arg < 0 || arg > max)

           throw new IllegalArgumentException(name +": " + arg);

    }

 

    public boolean equals(Object o) {

        if (o == this)

            return true;

        if (!(o instanceof PhoneNumber))

            return false;

        PhoneNumber pn = (PhoneNumber)o;

        return pn.extension == extension &&

               pn.exchange  == exchange  &&

               pn.areaCode  == areaCode;

    }

 

   /**如果没有改写hasCode方法,当将该类与HashMap结合使用时:

    * Map m = new HashMap();

    * m.put(new PhoneNumber(408,867,"Jenny");

    * 当你期望m.get(new PhoneNumber(408,867,"Jenny"))会返回"Jenny"时,它却返回null.

    * 因为这里涉及到两个PhoneNumber实例,前者插入到HashMap中,后者与前者相等,用于检索。

    * 由于没有改写hashCode,导致两个相等的实例具有不同的散列码,违反了hashCode约定。

    */

   

    /**Q:如何编写hashCode方法?

     * A:理想的散列函数应满足第3条约定——为不相等的对象产生不相等的散列码,

     *    把集合中不相等的实例均匀地分布到所有可能的散列值上。好的处方

     *    (1)把某个非零常数值,比如17,保存在一个变量里,比如:int result=17;

     *    (2)对于对象中的每个关键域f,完成以下步骤

     *       a. 如果该值是boolean类型,则计算(f?0:1)

     *       b.如果是byte,char,short或者int,则计算(int)f

     *       c.如果是long,则计算(int)(f^(f>>>32))

抱歉!评论已关闭.