Object之hashCode

本文详细介绍了Java中Object类的hashCode方法的基本概念与实现原理。包括hashCode的常规协定、与equals方法的关系以及hashCode在哈希表中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Object之hashCode

标签: objectequalsintegerstringapplicationcharacter
  4941人阅读  评论(0)  收藏  举报
  分类:

The original website:http://cjava.iteye.com/blog/441834

public int hashCode()返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。
hashCode 的常规协定是: 

在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有 
被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。 
如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。 
以下情况不 是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生
成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。 
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的 
,但是 JavaTM 编程语言不需要这种实现技巧。) 


返回: 
此对象的一个哈希码值。 
另请参见: 
equals(java.lang.Object), Hashtable 

其实这是一个本地方法,并不是用java实现的,这里的hashCode应是程式的地址入口,同一个对象的入口地址应是相同的. 
/** 
     * 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(); 
    
   很多方法都继承Object,其实这类中的toString()是我们经常用到,其实看源码可以他就是得到自己的类名及 
   hashCode的16进制型式。 
     /** 
     * Returns a string representation of the object. In general, the 
     * <code>toString</code> method returns a string that 
     * "textually represents" this object. The result should 
     * be a concise but informative representation that is easy for a 
     * person to read. 
     * It is recommended that all subclasses override this method. 
     * <p> 
     * The <code>toString</code> method for class <code>Object</code> 
     * returns a string consisting of the name of the class of which the 
     * object is an instance, the at-sign character `<code>@</code>', and 
     * the unsigned hexadecimal representation of the hash code of the 
     * object. In other words, this method returns a string equal to the 
     * value of: 
     * <blockquote> 
     * <pre> 
     * getClass().getName() + '@' + Integer.toHexString(hashCode()) 
     * </pre></blockquote> 
     * 
     * @return  a string representation of the object. 
     */ 
    public String toString() { 
return getClass().getName() + "@" + Integer.toHexString(hashCode()); 
    }
 
 
The five floor'answer:
 
java.lang.Object的约定如下: 
1,在程序的同一执行期间,如果equals方法的信息不给修改(前提),那么对同一对象多次调用hashcode得出的值也是必须一样。但是不要求在不同的执行期间保持一致 
2,如果两个对象的equals()方法等同,那么两对象任何一个调用hashCode()方法,必须产生同样的结果。 
3,如果两对象的equals()方法不相等,那么对两对象的任意对象调用hashCode()方法,不要求产生两个不同的整数结果 

hashcode   就仿佛是一个Object的ID,如果说它有什么特别,那就是它是一个int类型的值。在所有对象的运算中,int是最快(当然最快的是char,但是它能表达的信息太有限了)。一个简单的例子是Hashtable.contain(Object)方法,它首先是根据Object的散列值去判断,只有当出现多个相同的散列值的时候才会调用equals(),因为判断int比判断Object.equals()要快很多,这是一个提高效率的策略问题。同样也说明为什么不同的对象(equals()得false)具有不同的hashcode(也就是a.equal(b)==true   <=>   a.hashcode()==b.hashcode())具有更高效率的理由——不需要进行额外的equals()操作。 
<think>嗯,用户问的是ObjecthashCode有什么用。首先,我得回想一下Java中的hashCode方法。Object类是所有类的父类,所以每个对象都有hashCode方法。它的主要作用应该和哈希表有关,比如HashMap、HashSet这些集合类。 用户可能已经知道哈希表的基本概念,但想深入了解hashCode的具体用途。需要解释清楚hashCode在数据结构和算法中的作用。比如,哈希表通过hashCode快速定位元素,减少查找时间。 可能用户在使用HashMap时遇到了问题,比如键的重复或者性能问题,想了解如何正确实现hashCode来优化。这时候需要提到hashCode和equals方法的关系,两个方法必须一致,即如果两个对象equals相等,它们的hashCode也必须相等,反之不一定。 还要注意,默认的ObjecthashCode是基于内存地址生成的,所以即使两个对象内容相同,如果没有重写hashCode,它们的哈希码可能不同,导致在集合中出现问题。这时候需要强调重写hashCode的重要性,尤其是在自定义类作为键的时候。 用户可能对hashCode的实际应用场景不太清楚,可以举例子说明,比如在HashMap中存储键值对时,如何通过hashCode快速找到对应的桶,再通过equals方法确认键是否相等。如果hashCode设计不好,会导致很多对象堆积在同一个桶里,降低性能,变成链表甚至红黑树,影响效率。 另外,可能需要提到hashCode的一些约定,比如同一对象的hashCode在程序执行期间应保持一致,前提是equals比较的信息没有被修改。还有,不同对象的hashCode可以相同,这就是哈希冲突,好的hashCode方法应该尽量减少冲突。 用户可能还不太明白为什么需要hashCode和equals同时存在,这时候需要解释,hashCode用于快速定位,而equals用于精确匹配。两者配合使用,提高哈希表的效率。 最后,要提醒用户,当重写equals方法时,必须同时重写hashCode方法,确保两者的一致性。否则,在使用哈希集合时会出现不可预期的错误,比如对象无法正确被找到或者重复插入。 可能用户是刚开始学习Java,对对象比较和集合框架不太熟悉,所以需要用简单易懂的语言,结合实例说明,避免过于抽象。同时,用户可能想知道实际开发中如何正确实现hashCode,比如使用IDE自动生成,或者根据对象的字段生成哈希码,确保不同的对象有不同的哈希码,或者相同对象有相同哈希码。 总结一下,hashCode主要用于哈希表结构,帮助快速定位对象,提高存储和查询效率。正确实现hashCode和equals方法对于使用Java集合框架非常重要,尤其是在处理自定义对象作为键时。</think>在Java中,`Object`类的`hashCode()`方法是所有对象的“哈希码生成器”,它的核心作用是为对象提供**快速检索和高效存储的底层支持**,尤其是在哈希表(如`HashMap`、`HashSet`)等数据结构中。以下是详细解析: --- ### 一、hashCode的核心用途 #### 1. **哈希表的定位依据** - **哈希桶计算**:哈希表(如`HashMap`)通过`hashCode()`确定对象应存储在哪个“桶”(bucket)中。 例如:`hashCode % 桶数 = 桶索引`。 - **查找优化**:通过哈希码快速缩小查找范围,避免遍历所有元素(时间复杂度从$O(n)$降到接近$O(1)$)。 #### 2. **对象身份的辅助标识** - **配合`equals()`使用**: - 若两个对象`equals()`为`true`,它们的`hashCode()`必须相同(反之不一定成立)。 - 这一规则是Java集合框架(如`HashSet`去重、`HashMap`键匹配)正确运行的基础。 #### 3. **内存地址的间接映射** - **默认实现**:`Object`的默认`hashCode()`基于对象内存地址生成(但非直接等于地址值)。 示例代码: ```java Object obj = new Object(); System.out.println(obj.hashCode()); // 输出类似1523554304的整数 ``` --- ### 二、关键规则与约束 #### 1. **一致性规则** - 若对象未修改(`equals()`比较的信息不变),其`hashCode()`在同一程序执行期间必须一致。 #### 2. **哈希冲突容忍** - 允许不同对象有相同哈希码(哈希冲突),但应尽量减少冲突以提高性能。 ```java String s1 = "Aa"; // hashCode: 2112 String s2 = "BB"; // hashCode: 2112(哈希冲突) ``` #### 3. **重写要求** - **必须重写`hashCode()`的场景**: 当重写`equals()`方法时,必须同时重写`hashCode()`,否则破坏哈希集合的正确性。 ```java // 错误示例:仅重写equals()不重写hashCode() class Person { String name; public boolean equals(Object o) { /* 比较name */ } // 未重写hashCode() → 默认使用Object的哈希码 } ``` --- ### 三、实际应用场景 #### 场景1:`HashMap`的键匹配 ```java Map<Person, String> map = new HashMap<>(); Person p1 = new Person("Alice"); // 假设Person重写了hashCode和equals Person p2 = new Person("Alice"); map.put(p1, "Engineer"); System.out.println(map.get(p2)); // 输出"Engineer"(hashCode相同且equals为true) ``` #### 场景2:`HashSet`去重 ```java Set<Person> set = new HashSet<>(); set.add(new Person("Bob")); // hashCode: 12345 set.add(new Person("Bob")); // hashCode: 12345 → 视为重复,不添加 ``` #### 场景3:分布式系统的分片路由 - 例如,通过用户ID的哈希码决定数据存储到哪个数据库分片。 --- ### 四、如何正确重写hashCode() #### 推荐方法:基于关键字段生成 ```java @Override public int hashCode() { return Objects.hash(name, age); // 使用Java 7+的Objects工具类 } ``` #### 经典实现:Effective Java推荐公式 ```java @Override public int hashCode() { int result = 17; result = 31 * result + name.hashCode(); result = 31 * result + age; return result; } ``` **为什么用31?** - 31是奇素数,乘法可优化为位移运算:`31 * i = (i << 5) - i` - 减少哈希冲突(经验验证的平衡值) --- ### 五、常见误区与风险 | 错误行为 | 后果 | |--------------------------|------------------------------------------| | 仅重写`equals()`不重写`hashCode()` | `HashMap`/`HashSet`无法正确查找对象 | | 可变对象作为哈希键 | 修改对象后导致哈希码变化,集合行为异常 | | 哈希码过于简单(如直接返回固定值) | 哈希冲突剧增,性能退化为链表遍历($O(n)$)| --- ### 六、总结 1. **核心作用**:支持哈希表高效操作,是对象在哈希结构中的“身份证号”。 2. **协作规则**:必须与`equals()`保持一致,否则破坏集合的完整性。 3. **最佳实践**: - 重写`equals()`时必须重写`hashCode()` - 使用关键字段生成哈希码 - 避免可变对象作为哈希键
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值