Java HashCode

本文详细介绍了Java中hashCode方法的工作原理及其与equals方法的关系。解释了如何正确地重写这两个方法以确保对象的正确识别与比较,特别是针对自定义类的情况。

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

1.hashCode()用于返回调用该方法的对象的散列码值,此方法将返回整数形式的散列码值。

    在object类中,hashcode()方法是本地方法,返回的是对象的地址值,而object类中的equals()方法比较的也是两个对象的地址 值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了。一旦一个类重写equals()方法,通常也会重写 hashCode()方法。


2.java判断两个对象是否相等的规则
  首先,判断两个对象的hashCode是否相等;
  如果不相等,认为两个对象也不相等;
  如果相等,则判断两个对象用equals运算是否相等;
  如果不相等,认为两个对象也不相等;
  如果相等,认为两个对象相等。
  当我们重写了一个类的equals()方法后,我们一定要记住同时也要重写hashCode()方法。
  下面介绍如何来重写hashCode()方法。通常重写hashCode()方法按以下设计原则实现。
(1)把某个非零素数,例如17,保存在int型变量result中。
(2)对于对象中每一个关键域f(指equals方法中考虑的每一个域)参照以下原则处理。
  boolean型,计算(f?0:1)。
  byte、char和short型,计算(int)f。
  long型,计算(int)(f^(f>>32))。
  float型,计算Float.floatToIntBits(f)。
  double型,计算Double.doubleToLongBits(f)得到一个long,再执行long型的处理。
  对象引用,递归调用它的hashCode()方法。
  数组域,对其中的每个元素调用它的hashCode()方法。
(3)将上面计算得到的散列码保存到int型变量c,然后执行result = 37 * result + c。
(4)返回result。

3.String的hashcode方法

/**
     * Returns a hash code for this string. The hash code for a
     * <code>String</code> object is computed as
     * <blockquote><pre>
     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using <code>int</code> arithmetic, where <code>s[i]</code> is the
     * <i>i</i>th character of the string, <code>n</code> is the length of
     * the string, and <code>^</code> indicates exponentiation.
     * (The hash value of the empty string is zero.)
     *
     * @return  a hash code value for this object.
     */
    public int hashCode() {
    int h = hash;
        int len = count;
    if (h == 0 && len > 0) {
        int off = offset;
        char val[] = value;

            for (int i = 0; i < len; i++) {
                h = 31*h + val[off++];
            }
            hash = h;
        }
        return h;
    }

4.String的equals方法

/**
     * Compares this string to the specified object.  The result is {@code
     * true} if and only if the argument is not {@code null} and is a {@code
     * String} object that represents the same sequence of characters as this
     * object.
     *
     * @param  anObject
     *         The object to compare this {@code String} against
     *
     * @return  {@code true} if the given object represents a {@code String}
     *          equivalent to this string, {@code false} otherwise
     *
     * @see  #compareTo(String)
     * @see  #equalsIgnoreCase(String)
     */
    public boolean equals(Object anObject) {
	if (this == anObject) {
	    return true;
	}
	if (anObject instanceof String) {
	    String anotherString = (String)anObject;
	    int n = count;
	    if (n == anotherString.count) {
		char v1[] = value;
		char v2[] = anotherString.value;
		int i = offset;
		int j = anotherString.offset;
		while (n-- != 0) {
		    if (v1[i++] != v2[j++])
			return false;
		}
		return true;
	    }
	}
	return false;
    }


### Java 中 `hashCode` 的使用方法及实现原理 #### 1. **`hashCode` 的定义** `hashCode` 是 Java 中 Object 类的一个公共方法,返回的是一个整数类型的哈希码。该方法的主要作用是为对象提供一种快速比较的方式,尤其是在基于哈希的数据结构(如 HashMap、HashSet)中,用于加速查找操作[^3]。 --- #### 2. **`hashCode` 的实现原理** `hashCode` 方法的核心在于通过某种算法将对象映射到一个固定的整数值范围。这种映射通常依赖于对象的状态或属性。以下是常见的几种实现方式: - 对于基本数据类型数组,可以通过循环累加的方式来计算哈希值。例如,在字符串的 `hashCode` 实现中,采用了一种多项式累积的方法: ```java public static int hashCode(byte[] value) { int h = 0; for (byte v : value) { h = 31 * h + (v & 0xff); } return h; } ``` 这里选择了常量 31 作为乘子,因为它是质数,能够有效减少碰撞概率[^4]。 - 如果是一个自定义类的对象,则可以根据其字段的内容动态生成哈希值。例如: ```java @Override public int hashCode() { int result = 17; // 初始值 result = 31 * result + field1.hashCode(); // 字段1参与计算 result = 31 * result + field2.hashCode(); // 字段2参与计算 return result; } ``` --- #### 3. **`hashCode` 的使用场景** `hashCode` 主要应用于以下场景: - **哈希表中的索引计算** 在像 HashMap 或 HashSet 这样的集合中,`hashCode` 被用来决定对象存储的位置。具体来说,键的 `hashCode` 值会被转换成桶号(bucket index),从而加快检索速度[^1]。 - **对象相等性判断辅助** 当两个对象调用了 `equals()` 方法并返回 true 时,它们的 `hashCode` 应当相同;反之亦然。这是为了保证逻辑一致性[^2]。 --- #### 4. **注意事项与最佳实践** - **一致性原则** 只要在同一个应用程序执行期间多次调用某个对象的 `hashCode` 方法,并且在此过程中未修改影响哈希函数的结果的信息,那么该方法应当始终返回相同的整数[^1]。 - **分布均匀性** 设计良好的 `hashCode` 函数应尽量使不同对象产生的哈希值分布在较大的范围内,以降低冲突的可能性[^3]。 - **性能优化** 计算 `hashCode` 的开销不应过大,因此建议仅选取少数几个关键字段进行组合运算[^4]。 --- #### 5. **代码示例** 下面展示了一个简单的例子,说明如何在一个自定义类中覆盖默认的 `hashCode` 方法以及配合 `equals` 方法一起工作: ```java public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Person)) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { int result = 17; result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + age; return result; } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值