java如何重写hashcode
重写 hashCode 方法的原则
在 Java 中,hashCode() 方法用于返回对象的哈希码值,通常用于哈希表(如 HashMap 或 HashSet)中。重写 hashCode() 时需要遵循以下原则:
- 一致性:在对象未被修改的情况下,多次调用
hashCode()应返回相同的值。 - 相等性:如果两个对象通过
equals()方法判定为相等,它们的hashCode()必须返回相同的值。 - 不等性:如果两个对象通过
equals()方法判定为不相等,它们的hashCode()不一定要不同,但不同可以提高哈希表的性能。
重写 hashCode 的常见方法
使用 Objects.hash() 方法(Java 7+)
java.util.Objects 类提供了 hash() 方法,可以方便地生成哈希码:
@Override
public int hashCode() {
return Objects.hash(field1, field2, field3);
}
Objects.hash() 会为传入的字段生成一个组合哈希值。
手动实现哈希码计算
如果需要对哈希码生成进行更精细的控制,可以手动计算:
@Override
public int hashCode() {
int result = 17;
result = 31 * result + field1.hashCode();
result = 31 * result + (field2 == null ? 0 : field2.hashCode());
result = 31 * result + field3;
return result;
}
- 初始值通常选择一个非零质数(如 17)。
- 乘法因子 31 是一个奇质数,可以优化哈希分布。
- 对于基本类型,直接使用其包装类的
hashCode()或直接取值(如int)。
使用 Apache Commons Lang 的 HashCodeBuilder
如果项目中使用了 Apache Commons Lang,可以使用 HashCodeBuilder:
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(field1)
.append(field2)
.append(field3)
.toHashCode();
}
注意事项
- 不可变字段优先:哈希码计算应基于对象的不可变字段,否则可能导致哈希表行为异常。
- 避免冲突:尽量让不同对象的哈希码分布均匀,以减少哈希冲突。
- 与 equals() 同步:如果重写了
equals(),必须同时重写hashCode(),确保两者逻辑一致。 - 空值处理:如果字段可能为
null,需要显式处理(如返回 0 或其他默认值)。
示例代码
以下是一个完整的类示例,重写了 equals() 和 hashCode():
public class Person {
private String name;
private int age;
private String address;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name) &&
Objects.equals(address, person.address);
}
@Override
public int hashCode() {
return Objects.hash(name, age, address);
}
}






